[SERVER-377] Partial matching for sub objects Created: 21/Oct/09  Updated: 12/Jul/16  Resolved: 31/Dec/09

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

Type: New Feature Priority: Major - P3
Reporter: Zachary Gavin Assignee: Eliot Horowitz (Inactive)
Resolution: Done Votes: 17
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Any


Issue Links:
Depends
is depended on by SERVER-505 $all with regex Closed
Participants:

 Description   

There ought to be a way to partially match sub objects

Let's say you want to match this record:{a:[

{b:1,c:2,d:4}

,

{b:2,c:3,d:5}

]}

There is no simple way to partially map one of the objects that belongs to 'a'. If you do find({a:{b:1,c:2}}) currently, it will fail since sub objects must match exactly.

There are few work arounds:

You can match the sub object exactly, for example find({a:{b:1,c:2,d:4}}). This is far from ideal, because it means you have to know the format of your data before hand, which completely defeats the purpose of using a schemaless database.

You can use dot notation instead of a subobject, for example match against find(

{'a.b':1,'a.c':2}

). This will work, but it will also return incorrect results, for example find(

{'a.b':1,'a.c':3}

) will also match our document.

You can use a javascript function. This will return correct results, but It's also orders of magnitude slower in large collections, and requires maintaining the project in multiple languages. This approach also introduces an additional level of complexity that seems needless.

You can combine the second and third work arounds to fix incorrect results, but it's still difficult to maintain. You can also check the results of the the second method in your project's language, which eliminates the problem of having to generate javascript, but still seems overly complex.

Ideally you could partially match sub objects by use of a conditional operator something like this: find({a:{$partial_match:

{b:1,c:2}

}})



 Comments   
Comment by Karoly Negyesi [ 21/Jan/10 ]

Thanks! Note that if the alternative storage option gets implemented which I mentioned also would be fine. And then a query like {$exists: X : { 'primary.tag.und.tid.X': 61, 'primary.tag.und..fid.X': 1 }} would do the trick (declarative programming FTW). If primary.tag.und.tid (and fid) is indexed then this should be a fairly quick operation isnt it? grab the possible indexes, intersect, done?

Comment by Eliot Horowitz (Inactive) [ 21/Jan/10 ]

I see - that's not possible right now.
added a new case: http://jira.mongodb.org/browse/SERVER-562
please comment there with any questions and importance level

Comment by Karoly Negyesi [ 21/Jan/10 ]

Eliot, please see the structure earlier... Or, here is a simpler example:

Two documents:

{primary_tag:

{ und: [ { tid: 61,}

,

{ tid: 62,} { tid: 63,}

]}}

{primary_tag:

{ und: [ { tid: 61,}

,

{ tid: 2,} { tid: 3,}

]}}

I need documents which have both tid 61 and 62.

Of course, I could store {primary_tag: { und :

{ tid : [61,62,63 ]}

}} this way and use the $all operator. But then very soon we get back to the original issue with

{primary_tag: { und :

{ tid : [61,62,63 ], fid: [1,2,3] }

}}

wherein I need primary.tag.und..tid.X: 61, primary.tag.und..fid.X: 1 for the same X...

Comment by Eliot Horowitz (Inactive) [ 21/Jan/10 ]

@karoly Can you provide an example? I don't understand the question.

Comment by Karoly Negyesi [ 21/Jan/10 ]

What if I wanted to query such objects that have both value: body1 and value: body2 ?

Comment by Eliot Horowitz (Inactive) [ 31/Dec/09 ]

Note: if you have
{ a : [

{ x : 1 }

] }
and you do a query like
{ a : { $elemMatch : { x :

{ $gt : 1 }

} } }
if you index on "a.x" the index will be used.

Comment by Eliot Horowitz (Inactive) [ 31/Dec/09 ]

See: http://github.com/mongodb/mongo/blob/master/jstests/arrayfind1.js for examples.
Current name is $elemMatch, but may change until 1.3.1 is released

Comment by auto [ 31/Dec/09 ]

Author:

{'name': 'Eliot Horowitz', 'email': 'eliot@10gen.com'}

Message: query optimizer support for $elemMatch SERVER-377
http://github.com/mongodb/mongo/commit/0a3e1071cb4bb91d1c9c6cb36cac3a0337a97230

Comment by auto [ 31/Dec/09 ]

Author:

{'name': 'Eliot Horowitz', 'email': 'eliot@10gen.com'}

Message: basics os array element matching done SERVER-377 - doesn't work with query optimizer yet
http://github.com/mongodb/mongo/commit/c9de787f171db9abdfe9f580c7fc043b7806a1a4

Comment by Karoly Negyesi [ 17/Dec/09 ]

Drupal 7 field API would love this feature! We are storing fields like

"body" : { "zxx" : [

{ "summary" : "", "value" : "body1", "format" : "1", "value_format" : "1" }

,

{ "summary" : "", "value" : "body2", "format" : "2", "value_format" : "1" }

,

{ "summary" : "", "value" : "body3", "format" : "1", "value_format" : "1" }

] }

(zxx is ISO 639 for no language) and currently it's not possible to run a query which grabs value:body:2 format:2. If this would be possible then MongoDB would be a natural choice for Drupal 7 field storage. It works currently but we need to store separately for querying and it becomes ugly (and slower than necessary).

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