N1QL Performance when filtering on Array

I am running into a performance issue with a N1QL when i search for emails in the documents when stored in a ARRAY,
and there is only like 2700 docs in the _type “farm”
The query looks like this

SELECT
meta(f).id as DocId,
f.Owners.owner1FName  || IFMISSINGORNULL((CASE WHEN (LENGTH(f.Owners.owner1SpouseFName) > 0) THEN " & " || f.Owners.owner1SpouseFName || " "
ELSE " " END),  " ") || f.Owners.owner1LName as owner_1,
TRIM(f.Owners.owner2FName || IFMISSINGORNULL((CASE WHEN (LENGTH(f.Owners.owner2SpouseFName) > 0) THEN " & " || f.Owners.owner1SpouseFName || " "
ELSE " " END),  " ") || f.Owners.owner2LName) as owner2,
f.Marketing.privacy,
ARRAY { CASE WHEN v.type IS NOT MISSING  THEN lower(v.type)
   ELSE "default"
   END:
   CASE WHEN LENGTH(v. `number`) = 10 THEN
   "(" || SUBSTR(v.`number` , 0,3) || ") " || SUBSTR(v.`number` , 3,3) || "-" || SUBSTR(v.`number` , 6,4)
   else
   v.`number` END } FOR v IN f.phones END  AS phones,
   ARRAY {CASE WHEN v.type IS NOT MISSING  THEN lower(v.type)
      ELSE "default"
      END :v.`address`} FOR v IN f.emails END AS emails,
f.Marketing.farm_id,
f.PropertyAddress.houseNumber,
f.PropertyAddress.streetName,
f.PropertyAddress.city,
f.PropertyAddress.state,
f.beds,
f.baths,
f.partialBaths,
f.`pool`,
f.fireplace,
f.ownerOccupied,
f.tract,
t.name AS tract_name,
f.mailingAddress.address || " " || f.mailingAddress.city || " " ||
f.mailingAddress.state || " " || f.mailingAddress.zip ||"-" || f.mailingAddress.zip4 AS mailing_address
FROM Contacts AS f
LEFT JOIN Contacts AS t
ON t._type ="tract_info" AND ANY b IN t.tract_id SATISFIES b = f.tract END
WHERE f._type="farm" AND f.PropertyAddress.streetName IS NOT NULL  and ANY e IN f.emails SATISFIES LOWER(e.address) like LOWER("alex@test.com%") END order by f.PropertyAddress.streetName, TONUMBER(f.PropertyAddress.houseNumber) Limit 25 Offset 0

This is my current execution plan
{
#operator”: “Sequence”,
#stats”: {
#phaseSwitches”: 1,
“execTime”: “5.826µs”
},
“~children”: [
{
#operator”: “Authorize”,
#stats”: {
#phaseSwitches”: 3,
“execTime”: “7.476µs”,
“servTime”: “1.921884ms”
},
“privileges”: {
“List”: [
{
“Target”: “default:Contacts”,
“Priv”: 7
}
]
},
“~child”: {
#operator”: “Sequence”,
#stats”: {
#phaseSwitches”: 1,
“execTime”: “3.001µs”
},
“~children”: [
{
#operator”: “Sequence”,
#stats”: {
#phaseSwitches”: 2,
“execTime”: “193.303µs”,
“kernTime”: “124ns”,
“state”: “running”
},
“~children”: [
{
#operator”: “IndexScan3”,
#stats”: {
#itemsOut”: 2596,
#phaseSwitches”: 10387,
“execTime”: “23.043898ms”,
“kernTime”: “1.923394088s”,
“servTime”: “6.461892ms”
},
“as”: “f”,
“index”: “ix3”,
“index_id”: “6f197990a0147d0e”,
“index_order”: [
{
“keypos”: 0
},
{
“keypos”: 1
}
],
“index_projection”: {
“primary_key”: true
},
“keyspace”: “Contacts”,
“namespace”: “default”,
“spans”: [
{
“exact”: true,
“range”: [
{
“inclusion”: 0,
“low”: “null”
}
]
}
],
“using”: “gsi”,
#time_normal”: “00:00.0295”,
#time_absolute”: 0.02950579
},
{
#operator”: “Fetch”,
#stats”: {
#itemsIn”: 2596,
#itemsOut”: 2596,
#phaseSwitches”: 10713,
“execTime”: “27.279957ms”,
“kernTime”: “2.133884769s”,
“servTime”: “603.131602ms”
},
“as”: “f”,
“keyspace”: “Contacts”,
“namespace”: “default”,
#time_normal”: “00:00.6304”,
#time_absolute”: 0.630411559
},
{
#operator”: “Sequence”,
#stats”: {
#phaseSwitches”: 2,
“execTime”: “307.946µs”,
“kernTime”: “157ns”,
“state”: “running”
},
“~children”: [
{
#operator”: “NestedLoopJoin”,
#stats”: {
#itemsIn”: 2596,
#itemsOut”: 2664,
#phaseSwitches”: 24393,
“execTime”: “42.394898ms”,
“kernTime”: “3.121068801s”
},
“alias”: “t”,
“on_clause”: “((cover ((t._type)) = “tract_info”) and cover (any b in (t.tract_id) satisfies (b = (f.tract)) end))”,
“outer”: true,
“~child”: {
#operator”: “DistinctScan”,
#stats”: {
#itemsIn”: 1743,
#itemsOut”: 1743,
#phaseSwitches”: 25144,
“execTime”: “94.792488ms”,
“kernTime”: “2.983604824s”
},
“scan”: {
#operator”: “IndexScan3”,
#stats”: {
#itemsOut”: 1743,
#phaseSwitches”: 19952,
“execTime”: “81.570404ms”,
“kernTime”: “10.731157ms”,
“servTime”: “2.864292657s”
},
“as”: “t”,
“covers”: [
“cover ((distinct ((t.tract_id))))”,
“cover ((t.name))”,
“cover ((meta(t).id))”
],
“filter_covers”: {
“cover ((t._type))”: “tract_info”,
“cover (any b in (t.tract_id) satisfies (b = (f.tract)) end)”: true
},
“index”: “ix4”,
“index_id”: “df142ed4cdbbd26c”,
“index_projection”: {
“entry_keys”: [
1
],
“primary_key”: true
},
“keyspace”: “Contacts”,
“namespace”: “default”,
“nested_loop”: true,
“spans”: [
{
“exact”: true,
“range”: [
{
“high”: “(f.tract)”,
“inclusion”: 3,
“low”: “(f.tract)”
}
]
}
],
“using”: “gsi”
}
},
#time_normal”: “00:00.0423”,
#time_absolute”: 0.042394898
},
{
#operator”: “Filter”,
#stats”: {
#itemsIn”: 2664,
#itemsOut”: 2,
#phaseSwitches”: 5335,
“execTime”: “246.775648ms”,
“kernTime”: “2.916732909s”
},
“condition”: “((((f._type) = “farm”) and (((f.PropertyAddress).streetName) is not null)) and any e in (f.emails) satisfies (lower((e.address)) like lower("alex@test.com%”)) end)",
#time_normal”: “00:00.2467”,
#time_absolute”: 0.246775648
},
{
#operator”: “InitialProject”,
#stats”: {
#itemsIn”: 2,
#itemsOut”: 2,
#phaseSwitches”: 13,
“execTime”: “727.141µs”,
“kernTime”: “3.162784121s”
},
“result_terms”: [
{
“as”: “DocId”,
“expr”: “(meta(f).id)”
},
{
“as”: “owner_1”,
“expr”: “((((f.Owners).owner1FName) || ifmissingornull(case when (0 < length(((f.Owners).owner1SpouseFName))) then ((” & " || ((f.Owners).owner1SpouseFName)) || " ") else " " end, " “)) || ((f.Owners).owner1LName))”
},
{
“as”: “owner2”,
“expr”: “trim(((((f.Owners).owner2FName) || ifmissingornull(case when (0 < length(((f.Owners).owner2SpouseFName))) then ((” & " || ((f.Owners).owner1SpouseFName)) || " “) else " " end, " “)) || ((f.Owners).owner2LName)))”
},
{
“expr”: “((f.Marketing).privacy)”
},
{
“as”: “phones”,
“expr”: “array {case when ((v.type) is not missing) then lower((v.type)) else “default” end: case when (length((v.number)) = 10) then (((((”(” || substr0((v.number), 0, 3)) || ") “) || substr0((v.number), 3, 3)) || “-”) || substr0((v.number), 6, 4)) else (v.number) end} for v in (f.phones) end”
},
{
“as”: “emails”,
“expr”: “array {case when ((v.type) is not missing) then lower((v.type)) else “default” end: (v.address)} for v in (f.emails) end”
},
{
“expr”: “((f.Marketing).farm_id)”
},
{
“expr”: “((f.PropertyAddress).houseNumber)”
},
{
“expr”: “((f.PropertyAddress).streetName)”
},
{
“expr”: “((f.PropertyAddress).city)”
},
{
“expr”: “((f.PropertyAddress).state)”
},
{
“expr”: “(f.beds)”
},
{
“expr”: “(f.baths)”
},
{
“expr”: “(f.partialBaths)”
},
{
“expr”: “(f.pool)”
},
{
“expr”: “(f.fireplace)”
},
{
“expr”: “(f.ownerOccupied)”
},
{
“expr”: “(f.tract)”
},
{
“as”: “tract_name”,
“expr”: “cover ((t.name))”
},
{
“as”: “mailing_address”,
“expr”: "((((((((((f.mailingAddress).address) || " ") || ((f.mailingAddress).city)) || " ") || ((f.mailingAddress).state)) || " “) || ((f.mailingAddress).zip)) || “-”) || ((f.mailingAddress).zip4))”
}
],
#time_normal”: “00:00.0007”,
#time_absolute”: 0.0007271409999999999
},
{
#operator”: “FinalProject”,
#stats”: {
#itemsIn”: 2,
#itemsOut”: 2,
#phaseSwitches”: 5,
“execTime”: “3.742µs”
},
#time_normal”: “00:00.0000”,
#time_absolute”: 0.000003742
}
],
#time_normal”: “00:00.0003”,
#time_absolute”: 0.000307946
}
],
#time_normal”: “00:00.0001”,
#time_absolute”: 0.000193303
},
{
#operator”: “Limit”,
#stats”: {
#itemsIn”: 2,
#itemsOut”: 2,
#phaseSwitches”: 7,
“execTime”: “3.192µs”,
“kernTime”: “4.337µs”
},
“expr”: “25”,
#time_normal”: “00:00.0000”,
#time_absolute”: 0.000003192
}
],
#time_normal”: “00:00.0000”,
#time_absolute”: 0.0000030009999999999997
},
#time_normal”: “00:00.0019”,
#time_absolute”: 0.00192936
},
{
#operator”: “Stream”,
#stats”: {
#itemsIn”: 2,
#itemsOut”: 2,
#phaseSwitches”: 11,
“execTime”: “6.71µs”,
“kernTime”: “3.16547783s”
},
#time_normal”: “00:00.0000”,
#time_absolute”: 0.00000671
}
],
“~versions”: [
“2.0.0-N1QL”,
“6.0.0-1693-enterprise”
],
#time_normal”: “00:00.0000”,
#time_absolute”: 0.000005826
}

What is Index definition for ix3
Follow this article https://blog.couchbase.com/create-right-index-get-right-performance/

CREATE INDEX ix4 ON Contacts(PropertyAddress.streetName, TONUMBER(PropertyAddress.houseNumber), DISTINCT ARRAY LOWER(e.address) FOR e IN emails END) WHERE _type="farm";

Add the following to your query predicate

AND TONUMBER(f.PropertyAddress.houseNumber) IS NOT NULL