Behaviour of query/predicate does not match behaviour of MongoDB storage backend
torie opened this issue · comments
The behaviour of the filter operators in the query
package does not work when the document field being matched against is an array. For example, given the following document and query, the MongoDB storage backend will return a match, while the resource/testing/mem
backend will not.
Document
{ "foo": ["bar", "baz"] }
Query
{ field: { $in: ["bar"] } }
This is the case for the following operators, $eq
, $in
$ne
, $nin
.
Support for $in
and $nin
added in #188.
Support for $eq
and $ne
still need to be updated.
Accidentally clicked the close button...
I guess I can take on this.
Hmm, that is strange. First there is no $eq
operator in rest-layer
. I added these tests in predicate_test.go
and they are seem to be passing. I will test with real resource tomorrow, though.
{
`{"foo":["bar","baz"]}`, []test{
{map[string]interface{}{"foo": []interface{}{"bar", "baz"}}, true},
{map[string]interface{}{"foo": []interface{}{"bar"}}, false},
{map[string]interface{}{"foo": []interface{}{"baz"}}, false},
{map[string]interface{}{"foo": []interface{}{"bar", "baz", "tar"}}, false},
{map[string]interface{}{"foo": []interface{}{}}, false},
},
nil,
},
{
`{"foo":{$ne: ["bar","baz"]}}`, []test{
{map[string]interface{}{"foo": []interface{}{"bar", "baz"}}, false},
{map[string]interface{}{"foo": []interface{}{"bar"}}, true},
{map[string]interface{}{"foo": []interface{}{"baz"}}, true},
{map[string]interface{}{"foo": []interface{}{"bar", "baz", "tar"}}, true},
{map[string]interface{}{"foo": []interface{}{}}, true},
},
nil,
},
@torie Any comment appreciated.
{
`{"foo":"bar"}`, []test{
{map[string]interface{}{"foo": []interface{}{"bar", "baz"}}, true},
{map[string]interface{}{"foo": []interface{}{"bar"}}, true},
{map[string]interface{}{"foo": []interface{}{"baz"}}, false},
{map[string]interface{}{"foo": []interface{}{"bar", "baz", "tar"}}, true},
{map[string]interface{}{"foo": []interface{}{}}, false},
},
nil,
},
{
`{"foo":{$ne: "bar"}}`, []test{
{map[string]interface{}{"foo": []interface{}{"bar", "baz"}}, false},
{map[string]interface{}{"foo": []interface{}{"bar"}}, false},
{map[string]interface{}{"foo": []interface{}{"baz"}}, true},
{map[string]interface{}{"foo": []interface{}{"bar", "baz", "tar"}}, false},
{map[string]interface{}{"foo": []interface{}{}}, true},
},
nil,
},
The idea is what happens when you do a non-array query against an array field with MongDB:
https://docs.mongodb.com/manual/tutorial/query-arrays/#query-an-array-for-an-element
The idea is for the mem-backend and MongoDB backend to behave consistently for this cases. So that unit-tests are likely to match with MongoDB results (in production).
Okay, it checks if the value is in/not-in the array. Will implement this.
For the $ne
case in particular, it's worth double checking what the MongoDB implementation actually does before implementing.
The equal case is well documented in the linked docs, so that should be OK. I think we also tested this for equal, although we only needed it for $in and $nin when we did the first query.