How to query MongoDB to test if an item exists?

121,677

Solution 1

I dont believe that there is a straight way of checking the existence of the item by its value. But you could do that by just retrieving only id (with field selection)

db.your_collection.find({..criteria..}, {"_id" : 1});

Solution 2

Since you don't need the count, you should make sure the query will return after it found the first match. Since count performance is not ideal, that is rather important. The following query should accomplish that:

db.Collection.find({ /* criteria */}).limit(1).size();

Note that find().count() by default does not honor the limit clause and might hence return unexpected results (and will try to find all matches). size() or count(true) will honor the limit flag.

If you want to go to extremes, you should make sure that your query uses covered indexes. Covered indexes only access the index, but they require that the field you query on is indexed. In general, that should do it because a count() obviously does not return any fields. Still, covered indexes sometimes need rather verbose cursors:

db.values.find({"value" : 3553}, {"_id": 0, "value" : 1}).limit(1).explain();

{
  // ...
  "cursor" : "BtreeCursor value_1",
  "indexOnly" : true,  // covered!
}

Unfortunately, count() does not offer explain(), so whether it's worth it or not is hard to say. As usual, measurement is a better companion than theory, but theory can at least save you from the bigger problems.

Solution 3

Starting Mongo 2.6, count has a limit optional parameter, which makes it a viable alternative to find whether a document exists or not:

db.collection.count({}, { limit: 1 })
// returns 1 if exists and 0 otherwise

or with a filtering query:

db.collection.count({/* criteria */}, { limit: 1 })

Limiting the number of matching occurrences makes the collection scan stop whenever a match is found instead of going through the whole collection.


Starting Mongo 4.0.3, since count() is considered deprecated we can use countDocuments instead:

db.collection.countDocuments({}, { limit: 1 })

or with a filtering query:

db.collection.countDocuments({/* criteria */}, { limit: 1 })

Solution 4

It is significantly faster to use find() + limit() because findOne() will always read + return the document if it exists. find() just returns a cursor (or not) and only reads the data if you iterate through the cursor.

db.collection.find({_id: "myId"}, {_id: 1}).limit(1)

(instead of db.collection.findOne({_id: "myId"}, {_id: 1})).

Look at more details: Checking if a document exists – MongoDB slow findOne vs find

Solution 5

filter_dict = {"key":value}
if db.collection.count_documents(filter_dict):
    print("item is existed")
else:
    print("item is not existed")
Share:
121,677
user646584
Author by

user646584

Updated on July 08, 2022

Comments

  • user646584
    user646584 almost 2 years

    Does MongoDB offer a find or query method to test if an item exists based on any field value? We just want check existence, not return the full contents of the item.

  • moriesta
    moriesta over 10 years
    is db.Collection.find({ /* criteria */}).limit(1).size(); synchronous?
  • Arthur Tacca
    Arthur Tacca over 7 years
    You want .count(with_limit_and_skip=True). There is no method called .size()
  • Yuval A.
    Yuval A. over 6 years
    find() will always return a cursor (even if the document does not exist - in that case hasNext() will return false.
  • Stephen Smith
    Stephen Smith about 6 years
    There doesn't seem to be a .size() method
  • matang
    matang about 5 years
    I use findOne over find
  • fjc
    fjc almost 5 years
    Why use a framework if you can simply do result.length === 0?
  • Amin Shojaei
    Amin Shojaei almost 4 years
    Thanks. Since all IDs are indexed in the Memory, Will this query do anything with the disk?
  • BDL
    BDL over 3 years
    Although this code might solve the problem, a good answer should also explain what the code does and how it helps.