[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: |
|
||||||||
| 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. |
| 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 ] } } } } |
| Comment by Eliot Horowitz (Inactive) [ 31/Dec/09 ] |
|
See: http://github.com/mongodb/mongo/blob/master/jstests/arrayfind1.js for examples. |
| Comment by auto [ 31/Dec/09 ] |
|
Author: {'name': 'Eliot Horowitz', 'email': 'eliot@10gen.com'}Message: query optimizer support for $elemMatch |
| Comment by auto [ 31/Dec/09 ] |
|
Author: {'name': 'Eliot Horowitz', 'email': 'eliot@10gen.com'}Message: basics os array element matching done |
| Comment by Karoly Negyesi [ 17/Dec/09 ] |
|
Drupal 7 field API would love this feature! We are storing fields like "body" : { "zxx" : [ , , { "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). |