Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB Match an array with $type?

Tags:

I have a MongoDb collection contains of 284.116 tweets. The problem is the "author" field in some objects are in object type, but in other objects -this "author" field- are in array type. So the problem is I want to filter which ones are Array, and which ones are Object.

For example: The author field's type is object.

{     "_id" : ObjectId("55edfbd11a87d41d987a6dc1"),     "tweet" : "Back in my dorm, yay!",     "uri" : "https://twitter.com/natalylug0/status/640994018529181696",     "date" : "2015-09-08 00:04:17",     "country" : "U.S.A.",     "city" : "Texas",     "state" : "Dallas",     "author" : {         "username" : "Nataly",         "uri" : "https://twitter.com/natalylug0",         "screenname" : "natalylug0"     } } 

And the other one: The author field's type is array.

{     "_id" : ObjectId("55ee3a00e11fbb1030d659fe"),     "author" : [          {             "username" : "Relapsed Shini",             "uri" : "https://twitter.com/iPictoraL",             "screenname" : "iPictoraL"         }     ],     "tweet" : "@zumbiezuza 😍😍😍💚 ily zoeeeeeeee",     "uri" : "https://twitter.com/iPictoraL/status/641060812140900352",     "date" : "2015-09-08 01:29:42",     "country" : "U.S.A.",     "city" : "Texas",     "state" : "Dallas" } 

So I executed query like this:

db.getCollection('tweets').find({ author: { $type: 4} }) 

And what I get is

Fetched 0 record(s)  

But if execute $type:3 I get 284.116 values which is the same value of size of this collection.

So my question is, how can I filter objects which "author" fields contain arrays.

like image 249
Ali Yeşilkanat Avatar asked Sep 10 '15 22:09

Ali Yeşilkanat


People also ask

How to match element in array of MongoDB?

Match element in array of MongoDB? You can use $or operator along with limit (1) to match element in array. Let us first create a collection with documents − > db.matchElementInArrayDemo.insertOne( ...

What is the use of $type in MongoDB?

New in MongoDB 4.4 $type (Aggregation) - returns the BSON type of the argument. $type returns documents where the BSON type of the field matches the BSON type passed to $type. For documents where field is an array, $type returns documents in which at least one array element matches a type passed to $type.

What is the use of $size in MongoDB?

Introduction to MongoDB $size operator. The $size is an array query operator that allows you to select documents that have an array containing a specified number of elements. The $size operator has the following syntax: { array_field: {$size: element_count} } Code language: CSS (css)

Is the author field in a MongoDB collection array or object type?

I have a MongoDb collection contains of 284.116 tweets. The problem is the "author" field in some objects are in object type, but in other objects -this "author" field- are in array type. So the problem is I want to filter which ones are Array, and which ones are Object. For example: The author field's type is object.


1 Answers

Actually there is a "gotcha" listed in the documentation for $type specifically about arrays:

When applied to arrays, $type matches any inner element that is of the specified type. Without projection this means that the entire array will match if any element has the right type. With projection, the results will include just those elements of the requested type.

So that means that rather than detect whether the "element itself" is in array, what is actually being tested is the "inner element" of the array to see what type it is.

Now the documentation itself suggests this JavaScript test with $where:

.find({ "$where": "return Array.isArray(this.author)" }) 

But I think that's pretty horrible as there is a better way.

The trick is in "dot notation", where you ask for the 0 index element of the array to $exists

.find({ "author.0": { "$exists": true } }) 

Which is just the basic case that if the "0th" element exists then the field is present and the data is therefore an array.

Once you understand that logical premise then it is pretty simple test. The only thing that cannot be matched by that is a "truly empty" array, in which case you can fall back to the JavaScript alternative if needed. But this can actually use an index, so it would be preferred to use the latter form.

like image 127
Blakes Seven Avatar answered Sep 22 '22 01:09

Blakes Seven