[SERVER-12617] operators for explicit partial, exact ordered and unordered matching on dictionaries fields Created: 05/Feb/14  Updated: 10/Dec/14  Resolved: 20/Jun/14

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

Type: Improvement Priority: Major - P3
Reporter: aurelien lambert Assignee: Unassigned
Resolution: Done Votes: 0
Labels: dictionary, fieldname, fields, find, matching
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Participants:

 Description   

Hi

The more I look into MongoDB, the more Im confused by how MongoDB matches dictionaries fields.

Exact match and partial match of fields

It is not always explicit and sometimes tricky to guess if MongoDB will match the document only if all the fields are present (exact match) or if the fields described are a subset of the fields of the docuement (partial match).

Example on subdocuments

> db.test.insert({a:{a:1}});
> db.test.insert({a:{a:1,b:2}});
> db.test.insert({a:{a:1,b:2,c:3}});
> db.test.find({'a.a':1,'a.b':2}); // partial match
{a:{a:1,b:2}}
{a:{a:1,b:2,c:3}}
> db.test.find({a:{a:1,b:2}}); // exact match
{a:{a:1,b:2}}

Example on array items

> db.test.insert({a:[{a:1}]});
> db.test.insert({a:[{a:1,b:2}}});
> db.test.insert({a:[{a:1,b:2,c:3}]});
> db.test.find({a:{$elemMatch:{a:1,b:2}}}); // partial match
{a:[{a:1,b:2}]}
{a:[{a:1,b:2,c:3}]}
> db.test.find({a:{a:1,b:2}}); // exact match
{a:[{a:1,b:2}]}

Example on documents

> db.test.insert({a:1});
> db.test.insert({a:1,b:2});
> db.test.insert({a:1,b:2,c:3});
> db.test.find({'a':1,'b':2}); // partial match
{a:1,b:2}
{a:1,b:2,c:3}
> db.test.find({'':{a:1,b:2}}); // exact match ???
// Does not work :(

Order of the fields

The second point is that the order of the fields sometimes matters, sometimes not.

Example, the order matters when searching with exact match

> db.test.insert({a:{a:1,b:2}});
> db.test.insert({a:{b:2,a:1}});
> db.test.find({a:{a:1,b:2}}); // order matters
{a:{a:1,b:2}}

Example, the order does not matter when updating (or not)

> db.test.insert({a:{b:2,a:1}});
> db.test.update({}, {$set:{'a.b':'foo'}}); // reorders
> db.test.find();
{a:{a:1,b:'foo'}}

> db.test.insert({a:{b:2,a:1}});
> db.test.update({}, {$set:{'a.b':3}}); // keeps the order
> db.test.find();
{a:{b:3,a:1}}

> db.test.insert({a:{b:2,a:1}});
> db.test.update({}, {$set:{'a.c':'foo'}}); // reorders
> db.test.find();
{a:{a:1,b:2,c:'foo'}}

So on update, if the size of the object changes, fields are reordered in the alphabetic order (and '_id' is first). The first case could keep the order, but the last one is a bit more tricky, so keep the order on updates is not a simple thing.

What to do ?

My point is :

  • partial or exact matching is not explicit, and exact matching on documents is impossible
  • order matters on exact matching, but can be changed by updates

First, a full section about these points should be included in the documentation to avoid surprises
Second, the solution I see are 3 operators which make explicit which match id done. For instance :

  • $partial makes explict partial matching
  • $ordered makes explicit exact ordered matching
  • $unordered makes explicit exact unordered matching

Their name do not really matter, but I would like to have explicit operators to be sure for once of how my requests will be interpreted.

Thank you



 Comments   
Comment by Thomas Rueckstiess [ 20/Jun/14 ]

Hi Aurelien,

Here some pages from the documentation that might explain this better:

As for the order:

The _id field is moved to the front for performance reasons. In general, you shouldn't assume that your objects retain the attribute order. If you need ordered values, you can use an array instead.

Here some basic rules of thumb:

  1. If you use dot-notation to reach into sub-documents, e.g. {"a.b": 1, "a.c": 1}, partial matches are accepted and order does not matter
  2. If you use sub-document notation, e.g. {a: {b: 1, c: 1}}, the match has to be exact and order matters
  3. For arrays, use $elemMatch to confine the predicates to a single element in an array

As for the fact that you can't query on exact matches in your first "Example on documents", there is an open ticket SERVER-12199 that requests that already.

I hope you'll find these guidelines helpful.

Regards,
Thomas

Generated at Thu Feb 08 03:29:03 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.