[SERVER-1475] {field: {$type:"array"}} should return documents where "field" is an array Created: 24/Jul/10 Updated: 04/Nov/20 Resolved: 08/May/17 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Querying |
| Affects Version/s: | 1.4.4 |
| Fix Version/s: | 3.5.7 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Tatyana Tvardovskaya | Assignee: | David Storch |
| Resolution: | Done | Votes: | 14 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Ubuntu 10.04(lucid), x64 |
||
| Issue Links: |
|
||||||||||||||||||||||||||||||||
| Backwards Compatibility: | Minor Change | ||||||||||||||||||||||||||||||||
| Operating System: | ALL | ||||||||||||||||||||||||||||||||
| Sprint: | Query 2017-05-08, Query 2017-05-29 | ||||||||||||||||||||||||||||||||
| Participants: | |||||||||||||||||||||||||||||||||
| Description |
|
Operator $type does not finds array (type=4) elements. It tested db, 'aList' field is array. There are records with empty arrays and not empty. Meantime, the following check shows that there are arrays, and som of them are non-empty: > var zero = db.mydata.count({ aList: {$size: 0 } }); //empty arrays As you see, obj == (all - zero) - all arrays are treated as Objects(type=3)! |
| Comments |
| Comment by David Storch [ 12/May/17 ] | |||||||||||||||||||||||||||||
|
This change will affect users on 3.4.x who have partial indexes whose partialFilterExpression has a $type:"array" expression and wish to upgrade to 3.6. As part of the upgrade process, such users must rebuild any such partial index when first starting a 3.6 node. Failing to do so could cause the user to experience a mix of the old and new $type:"array" semantics. We should clearly document this wrinkle in the 3.6 compatibility notes so that users who may be affected can take the appropriate action. Note that this also applies to $type:4, since 4 is the type code for BSON arrays. | |||||||||||||||||||||||||||||
| Comment by Githook User [ 08/May/17 ] | |||||||||||||||||||||||||||||
|
Author: {u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}Message: Prior to this change, the semantics of $type were that it but not {x: [1, 2, 3]}. This is inconsistent with the matching semantics for The new behavior is that single-level arrays as well as | |||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 02/Feb/17 ] | |||||||||||||||||||||||||||||
|
As of 3.4 the proposed workaround works fine on two dimensional arrays too:
| |||||||||||||||||||||||||||||
| Comment by aurelien lambert [ 06/Mar/14 ] | |||||||||||||||||||||||||||||
|
The javascript workaround is as said not efficient, and then non javascript workaround requires an $or at the root, which makes it tricky if one needs to check if several fields are arrays. Wouldn't it be more simple if the $all:[] could do it ? It would look like
Isn't it simple ? | |||||||||||||||||||||||||||||
| Comment by Thomas Zahn [ 14/Feb/14 ] | |||||||||||||||||||||||||||||
|
That's a nice work-around, however it doesn't work for nested arrays.
Suppose one now wanted to explicitly find those documents where a specific element of a (e.g. a.0) is again an array, i.e. a 2-dimensional array. Unfortunately, only $size seems to work on a.0, whereas $elemMatch fails:
This seems related to the following reported bug in $elemMatch: | |||||||||||||||||||||||||||||
| Comment by Tobia Conforto [ 02/Oct/13 ] | |||||||||||||||||||||||||||||
|
Here is an updated workaround to deal with the edge case of a document with key "0":
It tests for a non-empty array using $elemMatch instead of .0 | |||||||||||||||||||||||||||||
| Comment by A. Jesse Jiryu Davis [ 05/Jun/12 ] | |||||||||||||||||||||||||||||
|
What about adding an $isArray operator to deal with the specific use-case of determining if a field is of array type, while leaving the $type operator's current behavior--matching elements of the array rather than the array itself, consistent with other operators? | |||||||||||||||||||||||||||||
| Comment by Daniel Gottlieb (Inactive) [ 13/Apr/12 ] | |||||||||||||||||||||||||||||
|
As a caveat, doing an existence test for "a.0" will also match a document such as: {"_id": ..., "a": {"0": "foo", "name": "bar"}}, but I'll venture it's an unlikely edge case. test:PRIMARY> db.test.find({$or: [ {x: []}, {'x.0': {$exists: true}}]}) { "_id" : ObjectId("4f885a1a3b5c50b21c2f5311"), "x" : [ ] } { "_id" : ObjectId("4f885a213b5c50b21c2f5312"), "x" : [ "1" ] }{ "_id" : ObjectId("4f885b923b5c50b21c2f5314"), "x" : { "0" : "foo", "name" : "bar" }} | |||||||||||||||||||||||||||||
| Comment by Robert Stam [ 13/Apr/12 ] | |||||||||||||||||||||||||||||
|
Here's a workaround that doesn't involve Javascript:
The existence test for "a.0" doesn't detect empty arrays, but if you need to find empty arrays also you can combine it with a test for {$size:0}. | |||||||||||||||||||||||||||||
| Comment by Scott Hernandez (Inactive) [ 13/Apr/12 ] | |||||||||||||||||||||||||||||
|
You can use javascript to do the test but that is not very efficient:
| |||||||||||||||||||||||||||||
| Comment by Luc Dobler [ 13/Feb/12 ] | |||||||||||||||||||||||||||||
|
Does anyone have a workaround to this ? | |||||||||||||||||||||||||||||
| Comment by Ara T. Howard [ 05/Feb/12 ] | |||||||||||||||||||||||||||||
|
i would say there are four things that make this a bug: 1) the docs clearly state this is the expected behavior http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24type 2) without such a feature the query 'where the field "foo" is an array' is impossible, which would be a shame in a schema free document oriented database... 3) searches for $type==3 (object) return arrays, which is extremely counter intuitive 4) searchers for $type==anthing (int, string, etc) return not only where the field has that type, but also where there might exist that type wrapped by an array. | |||||||||||||||||||||||||||||
| Comment by Alex Litvinok [ 02/Dec/11 ] | |||||||||||||||||||||||||||||
|
This problem in PHP driver is expressed:
Returned as:
Also, if embedded array:
Returned as:
| |||||||||||||||||||||||||||||
| Comment by Uladzimir Mihura [ 30/Nov/11 ] | |||||||||||||||||||||||||||||
|
>db.tmp.insert( {"title":"The Godfather","keywords":["test","word","cool"]}) ) Actually it is looking inside the array and not at the field itself. -vova | |||||||||||||||||||||||||||||
| Comment by Dwight Merriman [ 18/Apr/11 ] | |||||||||||||||||||||||||||||
|
> t.find() { "_id" : ObjectId("4dac8e746d2750035ba0e326"), "x" : [ 1, 2, 3 ] } { "_id" : ObjectId("4dac8f376d2750035ba0e327"), "x" : 9 }{ "_id" : ObjectId("4dac90d16d2750035ba0e328"), "x" : { "y" : 3 } } } ) } } ) } ) { "_id" : ObjectId("4dac8e746d2750035ba0e326"), "x" : [ 1, 2, 3 ] } { "_id" : ObjectId("4dac8f376d2750035ba0e327"), "x" : 9 } | |||||||||||||||||||||||||||||
| Comment by Fitz Agard [ 24/Feb/11 ] | |||||||||||||||||||||||||||||
|
Along the lines of the above, is there any way to identify the overal field as an array irrespective of what the values are? Thanks, | |||||||||||||||||||||||||||||
| Comment by Robert Slifka [ 26/Sep/10 ] | |||||||||||||||||||||||||||||
|
Hi Eliot, Thanks for the tip! Appreciate the quick response What is the intended use of type:4? Rob | |||||||||||||||||||||||||||||
| Comment by Eliot Horowitz (Inactive) [ 26/Sep/10 ] | |||||||||||||||||||||||||||||
|
This is actually not a bug per se. | |||||||||||||||||||||||||||||
| Comment by Robert Slifka [ 26/Sep/10 ] | |||||||||||||||||||||||||||||
|
I'm actually seeing them as strings (1.4.4 as well). > db.type_test.insert( {rob:['is','cool']}) > db.type_test.find({'rob':{$type:4}}) > | |||||||||||||||||||||||||||||
| Comment by Tatyana Tvardovskaya [ 24/Jul/10 ] | |||||||||||||||||||||||||||||
|
Could be linked to similar bug http://jira.mongodb.org/browse/JAVA-103 |