663

I would like to execute a following query:

db.mycollection.find(HAS IMAGE URL)

What should be the correct syntax?

darijan
  • 9,725
  • 25
  • 38
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • 130
    Short answer: the query `{ field : {$ne : null} }` check for not-null http://docs.mongodb.org/manual/reference/operator/query/ne/ – Jaider Jul 08 '15 at 13:31

11 Answers11

1230

This will return all documents with a key called "IMAGE URL", but they may still have a null value.

db.mycollection.find({"IMAGE URL":{$exists:true}});

This will return all documents with both a key called "IMAGE URL" and a non-null value.

db.mycollection.find({"IMAGE URL":{$ne:null}});

Also, according to the docs, $exists currently can't use an index, but $ne can.

Edit: Adding some examples due to interest in this answer

Given these inserts:

db.test.insert({"num":1, "check":"check value"});
db.test.insert({"num":2, "check":null});
db.test.insert({"num":3});

This will return all three documents:

db.test.find();

This will return the first and second documents only:

db.test.find({"check":{$exists:true}});

This will return the first document only:

db.test.find({"check":{$ne:null}});

This will return the second and third documents only:

db.test.find({"check":null})
Tim Gautier
  • 29,150
  • 5
  • 46
  • 53
  • 21
    According to docs, `$ne` **includes documents that do not contain the field**. Has this changed since you posted the answer? http://docs.mongodb.org/manual/reference/operator/query/ne/ – Andrew Mao Sep 24 '14 at 04:40
  • 6
    I don't believe that has changed. When checking $ne, the value is checked in all documents, including those that don't contain the field, but $ne:null still will not match a document that does not contain the field since the value of the field is still null, even though the field doesn't exist in that document. – Tim Gautier Sep 24 '14 at 17:39
  • @TimGautier, are you saying `$ne:null` will __not__ match a document missing the field _because_ the value __is__ `null`? Shouldn't it not match the document because the value is __not__ null? – James M. Lay Feb 22 '15 at 21:47
  • 1
    $ne:null will not match a document that does not have that field because the value of the non-existent field is null and $ne:null is looking for fields that are not equal to null. So the answer to your questions are yes for the first and no for the second. – Tim Gautier Feb 24 '15 at 17:43
  • In the other hand, `$eq:null` help you to find those records that have missing data. – Jaider Jun 05 '15 at 14:02
  • 2
    How do you just match the second document? – B T Apr 21 '16 at 07:34
  • @TimGautier that's incorrect. Your second-to-last query will return the first and third documents. Unintuitive, but try it out and see for yourself. – River Nov 08 '17 at 03:24
  • 3
    @River I checked when I wrote this 3 years ago and, just to be sure, I just installed Mongo and tried it out again. It still works the same way, the answer is correct. The 2nd to last query returns only the 1st document. – Tim Gautier Nov 08 '17 at 16:54
  • 1
    @TimGautier odd, I just did the same myself and you're right. This is complete counter to what the `$ne` docs state. – River Nov 08 '17 at 17:07
  • @TimGautier oh I see, it's because all fields are implicitly contained with a `null` value. – River Nov 08 '17 at 17:11
  • @AndrewMao, I was confused about this too, until I came across the docs that explain how types are compared: https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#non-existent-fields – Marconius Jun 19 '19 at 13:28
  • 2
    The examples given make it really understandable how to use this. :-) – Eric Dela Cruz Dec 21 '19 at 03:45
  • The examples given make it really understandable how to use this. :-) – Shridutt Kothari May 17 '22 at 10:12
152

One liner is the best :

db.mycollection.find({ 'fieldname' : { $exists: true, $ne: null } });

Here,

mycollection : place your desired collection name

fieldname : place your desired field name

Explaination :

$exists : When is true, $exists matches the documents that contain the field, including documents where the field value is null. If is false, the query returns only the documents that do not contain the field.

$ne selects the documents where the value of the field is not equal to the specified value. This includes documents that do not contain the field.

So in your provided case following query going to return all the documents with imageurl field exists and having not null value:

db.mycollection.find({ 'imageurl' : { $exists: true, $ne: null } });
Amitesh Bharti
  • 14,264
  • 6
  • 62
  • 62
  • 26
    `$exists: true` is redundant, `$ne: null` is enough. – Stanislav Karakhanov Nov 21 '18 at 20:13
  • 1
    This should be the best answer. `$exists: true` returns `null` values too. There has to be both `$exists: true` and `$ne: null`. It's NOT redundant. – Ismail Kattakath Jun 01 '20 at 19:16
  • 7
    @IsmailKattakath the `$ne: null` makes `$exists: true` — by your own explanation! Since `$exists: true` returns `null` values, and `$ne: null` filters those out, all you need is `$ne: null` – jessepinho Jun 30 '20 at 11:15
67
db.collection_name.find({"filed_name":{$exists:true}});

fetch documents that contain this filed_name even it is null.

Warning

db.collection_name.find({"filed_name":{$ne:null}});

fetch documents that its field_name has a value $ne to null but this value could be an empty string also.

My proposition:

db.collection_name.find({ "field_name":{$ne:null},$where:"this.field_name.length >0"})
Farouk Elkholy
  • 913
  • 7
  • 10
59

In pymongo you can use:

db.mycollection.find({"IMAGE URL":{"$ne":None}});

Because pymongo represents mongo null as python None.

ParkerM
  • 302
  • 1
  • 4
  • 17
user2293072
  • 766
  • 6
  • 9
20

Sharing for future readers.

This query worked for us (query executed from MongoDB compass):

{
  "fieldName": {
    "$nin": [
      "",
      null
    ]
  }
}
Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
12

In an ideal case, you would like to test for all three values, null, "" or empty(field doesn't exist in the record)

You can do the following.

db.users.find({$and: [{"name" : {$nin: ["", null]}}, {"name" : {$exists: true}}]})
Phoenix
  • 3,996
  • 4
  • 29
  • 40
Ankit Marothi
  • 955
  • 10
  • 14
4

The simplest way to check the existence of the column in mongo compass is :

{ 'column_name': { $exists: true } }
Taha Hamedani
  • 105
  • 1
  • 11
  • 1
    The problem with this is that it assumes the field genuinely was never persisted, but the OP seems to indicate (from the headline) that it could exist but be set to null explicitly. – Carighan Apr 24 '20 at 08:09
3

An alternative that has not been mentioned, but that may be a more efficient option for some (won't work with NULL entries) is to use a sparse index (entries in the index only exist when there is something in the field). Here is a sample data set:

db.foo.find()
{ "_id" : ObjectId("544540b31b5cf91c4893eb94"), "imageUrl" : "http://example.com/foo.jpg" }
{ "_id" : ObjectId("544540ba1b5cf91c4893eb95"), "imageUrl" : "http://example.com/bar.jpg" }
{ "_id" : ObjectId("544540c51b5cf91c4893eb96"), "imageUrl" : "http://example.com/foo.png" }
{ "_id" : ObjectId("544540c91b5cf91c4893eb97"), "imageUrl" : "http://example.com/bar.png" }
{ "_id" : ObjectId("544540ed1b5cf91c4893eb98"), "otherField" : 1 }
{ "_id" : ObjectId("544540f11b5cf91c4893eb99"), "otherField" : 2 }

Now, create the sparse index on imageUrl field:

db.foo.ensureIndex( { "imageUrl": 1 }, { sparse: true } )
{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

Now, there is always a chance (and in particular with a small data set like my sample) that rather than using an index, MongoDB will use a table scan, even for a potential covered index query. As it turns out that gives me an easy way to illustrate the difference here:

db.foo.find({}, {_id : 0, imageUrl : 1})
{ "imageUrl" : "http://example.com/foo.jpg" }
{ "imageUrl" : "http://example.com/bar.jpg" }
{ "imageUrl" : "http://example.com/foo.png" }
{ "imageUrl" : "http://example.com/bar.png" }
{  }
{  }

OK, so the extra documents with no imageUrl are being returned, just empty, not what we wanted. Just to confirm why, do an explain:

db.foo.find({}, {_id : 0, imageUrl : 1}).explain()
{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 6,
    "nscannedObjects" : 6,
    "nscanned" : 6,
    "nscannedObjectsAllPlans" : 6,
    "nscannedAllPlans" : 6,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "server" : "localhost:31100",
    "filterSet" : false
}

So, yes, a BasicCursor equals a table scan, it did not use the index. Let's force the query to use our sparse index with a hint():

db.foo.find({}, {_id : 0, imageUrl : 1}).hint({imageUrl : 1})
{ "imageUrl" : "http://example.com/bar.jpg" }
{ "imageUrl" : "http://example.com/bar.png" }
{ "imageUrl" : "http://example.com/foo.jpg" }
{ "imageUrl" : "http://example.com/foo.png" }

And there is the result we were looking for - only documents with the field populated are returned. This also only uses the index (i.e. it is a covered index query), so only the index needs to be in memory to return the results.

This is a specialized use case and can't be used generally (see other answers for those options). In particular it should be noted that as things stand you cannot use count() in this way (for my example it will return 6 not 4), so please only use when appropriate.

Adam Comerford
  • 21,336
  • 4
  • 65
  • 85
3
db.<collectionName>.find({"IMAGE URL":{"$exists":"true"}, "IMAGE URL": {$ne: null}})
  • 1
    Is this a valid Json document? Two properties with the same name in the query document. Not sure how you would build that in memory if you had to. – BrentR Oct 02 '18 at 15:21
1

You can use $and and $exists with $nin for finding the scenario for not null value for the key.

use dbname db.collectionname.find({$and : [{key : {$exists : true}},{$nin : [null,'',undefined]}]});

Since a value can either be present or not present. For that case $exists will work to check the value. And for the case where value exists to check the details of that, $nin is used to exclude undefined, null and empty string.

SahilTyagi
  • 27
  • 1
  • 1
  • 8
-5

Thanks for providing a solution, I noticed in MQL, sometimes $ne:null doesn't work instead we need to use syntax $ne:"" i.e. in the context of above example we would need to use db.mycollection.find({"IMAGE URL":{"$ne":""}}) - Not sure why this occurs, I have posted this question in the MongoDB forum.

following is the snapshot showing example:

enter image description here

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Punya
  • 11
  • Please consider to post your answer with text instead of screenshot. https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors – haudoing Jan 18 '21 at 03:19
  • BTW take a look on data type https://docs.mongodb.com/manual/reference/bson-types/ – haudoing Jan 18 '21 at 03:20
  • 1
    The screenshot is showing that you have empty strings saved in the DB. Those may not be useful, but they're also not null, so it's working as expected. – Tim Gautier Jan 18 '22 at 17:13
  • `{$ne: null}` checks for the field value is not `null` meaning all documens that have the field and the value will come up in the query. if you use `{$ne: ""}` checks that the field exists and is not equal to the empty string `''`. If you whether want to check if the field exists you can use {fieldName: {$exists:true}} – fp007 Jul 11 '23 at 19:01