[SERVER-30197] $eq-ordered and $eq-unordered Created: 17/Jul/17  Updated: 06/Dec/22

Status: Backlog
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Karolin Varner Assignee: Backlog - Query Optimization
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-5030 Document equality should be independe... Backlog
Assigned Teams:
Query Optimization
Participants:

 Description   

It would be nice if there where specialized variants of the $eq operator for matching in an order-Independent fashion.

$eq-unordered could be used on arrays to implement sets:

> db.test.insert({_id: 1, colors: ["red", "blue"]})
> db.test.find({colors: {$eq-unordered: ["blue", "red"]}})
{_id: 1, colors: ["red", "blue"]})

For objects it would be useful, since json objects are usually treated as order-independent by most programming environment, so this would make subdocument matching easier.

Without this we have to do:

> db.test.insert({_id: 1, doc: {name: "Arthur", occupation: "Bulldozer-preventer"}})
> db.test.insert({_id: 2, doc: {name: "Arthur", occupation: "Bulldozer-preventer", do_not_ignore: "do not ignore this field"}})
> db.test.find({"doc.name": "Arthur", "doc.occupation": "Bulldozer-preventer"})
{_id: 1, doc: {name: "Arthur", occupation: "Bulldozer-preventer"}}
{_id: 2, doc: {name: "Arthur", occupation: "Bulldozer-preventer", do_not_ignore: "do not ignore this field"}}

Note how the second document also is matched – I believe there is no syntax to prevent the match if there are extra fields so an exact order independant match is not possible.

With this we could do:

> db.test.find({doc: {$eq-unordered: {occupation: "Bulldozer-preventer", name: "Arthur"}}})
{_id: 1, doc: {name: "Arthur", occupation: "Bulldozer-preventer"}}



 Comments   
Comment by Asya Kamsky [ 10/Aug/17 ]

Some aggregation expressions will become available in find/update query in 3.6 which is why I mentioned it.

Not promising that *this* use case will be solved in 3.6 though.

Comment by Karolin Varner [ 09/Aug/17 ]

Hi, $setEquals is for aggregation and thus specifically not usable for querying (only querying is available in update so no feature from aggregation can be used for the update-and-replace idom)

SERVER-5030 sounds great

Comment by Asya Kamsky [ 09/Aug/17 ]

If we implement SERVER-5030 it may make this request unnecessary for objects.

For arrays, there is already $setEquals expression that might be helpful.

Comment by Asya Kamsky [ 21/Jul/17 ]

This is a reasonable request which may require introducing a new comparison operator.

In the current version (3.4.4 or later) it is possible to perform such comparison using aggregation framework.

For arrays:

db.test.aggregate([
   {$match:{colors:{$all:["blue", "red"]}}},
   {$addFields:{__compare:{$setEquals:["$colors",["blue", "red"]]}}},
   {$match:{__compare:true}}
])

For objects:

db.test.aggregate([
   {$match:{"doc.name": "Arthur", "doc.occupation": "Bulldozer-preventer"}}, 
   {$addFields:{__otherFields:{$setEquals:[
             {$objectToArray: { "name" : "Arthur", "occupation" : "Bulldozer-preventer" }},
             {$objectToArray:"$doc"}
   ]}}},
   {$match:{__otherFields:true}}
])

Comment by Mark Agarunov [ 19/Jul/17 ]

Hello karo,

Thank you for the detailed example. I've set the fixVersion to "Needs Triage" for this new feature to be scheduled against our currently planned work. Updates will be posted on this ticket as they happen.

Thanks,
Mark

Generated at Thu Feb 08 04:23:00 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.