Hi there,
Have discovered something unexpected with arrays in documents referenced in indexes, and the results that indexes produce.
While you cannot place a field that is an array into the value section of an index where the term of the index only points to the document reference (you will get null / empty for the field - expected behaviour) you can of course place a field that points to an array in the term section.
Example Document in TestArray collection
{
"name": "Array One",
"options": [
Ref(Collection("Options"), "351011260955886162"),
Ref(Collection("Options"), "351011279983346265"),
Ref(Collection("Options"), "351011349946434132")
]
}
Index 1
The first index looks like this:
CreateIndex({
name: "TestArray_by_ref_1",
unique: false,
serialized: false,
source: Collection("TestArray"),
terms: [
{ field: ["ref"] },
{ field: ["data", "options"] }
],
values: [
{ field: ["ref"] }
]
})
Query 1
The purpose is to test if an option is present in a document.
Let’s check:
Paginate(
Match(
Index("TestArray_by_ref_1"),
Ref(Collection("TestArray"), "351003461841584722"),
Ref(Collection("Options"), "351011260955886162")
)
)
As Expected
Which will return ONE match, because there is of course only one match:
{
data: [Ref(Collection("TestArray"), "351003461841584722")]
}
The Question
What if we have an array of options as input, and we want to find out which ones of those the document has, and output them as an array?
With the current index we can of course create a query that goes through the input array, repeatedly queries the index for each one, keeping track of the option queried for each time, and then build a new array of those options that match one by one (this is something I have not actually done. but I seem to remember reading something somewhere where someone did manage this).
On the other hand, if we could just grab the option reference directly from the index’s output, and further simply wrap everything in a Paginate to create a simpler query that produces an array that can be consumed by something else - that would be cool.
So, we update the index to contain the array in the value as well - even though it is not expected to work on its own, since the index knows the value pulled from the array as it is in TERMS, perhaps it would be kind enough to copy that to the VALUES as well?
Thought I would give it a try:
CreateIndex({
name: "TestArray_by_ref_2",
unique: false,
serialized: false,
source: Collection("TestArray"),
terms: [
{ field: ["ref"] },
{ field: ["data", "options"] }
],
values: [
{ field: ["data", "options"] }
{ field: ["ref"] },
]
})
So this time when we do a query, maybe, just maybe the options field will contain the item filtered to:
Paginate(
Match(
Index("TestArray_by_ref_2"),
Ref(Collection("TestArray"), "351003461841584722"),
Ref(Collection("Options"), "351011260955886162")
)
)
It would be very useful if it were to produce this:
{
data: [
Ref(Collection("Options"), "351011260955886162"),
Ref(Collection("TestArray"), "351003461841584722")
}
However, surprisingly it produces the following:
{
data: [
[
Ref(Collection("Options"), "351011260955886162")
Ref(Collection("TestArray"), "351003461841584722")
],
[
Ref(Collection("Options"), "351011279983346265"),
Ref(Collection("TestArray"), "351003461841584722")
],
[
Ref(Collection("Options"), "351011349946434132"),
Ref(Collection("TestArray"), "351003461841584722")
]
]
}
I realise this is an edge case, and is not documented behaviour.
At present arrays are not meant to be in the values section of indexes, however I thought it was interesting that this happened, and I wondered if there are any plans to tweak the index system to be able to support arrays if they were used in this fashion - such that the value that matches in the terms section is made available to the values section to support simpler queries.
Thanks for taking the time to read this.