【发布时间】:2022-04-05 14:34:54
【问题描述】:
MongoDB 是否提供查找或查询方法来根据任何字段值测试项目是否存在?我们只想检查是否存在,而不是返回项目的全部内容。
【问题讨论】:
MongoDB 是否提供查找或查询方法来根据任何字段值测试项目是否存在?我们只想检查是否存在,而不是返回项目的全部内容。
【问题讨论】:
由于您不需要计数,因此您应该确保查询将在找到第一个匹配项后返回。因为count performance is not ideal,这很重要。以下查询应该完成:
db.Collection.find({ /* criteria */}).limit(1).size();
请注意,find().count() 默认情况下不尊重limit 子句,因此可能会返回意外结果(并会尝试查找所有匹配项)。 size() 或 count(true) 将遵守限制标志。
如果你想走极端,你应该确保你的查询使用covered indexes。覆盖索引仅访问索引,但它们要求您查询的字段已编入索引。一般来说,应该这样做,因为 count() 显然不返回任何字段。不过,覆盖索引有时需要相当冗长的游标:
db.values.find({"value" : 3553}, {"_id": 0, "value" : 1}).limit(1).explain();
{
// ...
"cursor" : "BtreeCursor value_1",
"indexOnly" : true, // covered!
}
很遗憾,count() 不提供explain(),所以值得与否很难说。像往常一样,测量是比理论更好的伴侣,但理论至少可以让你摆脱更大的问题。
【讨论】:
db.Collection.find({ /* criteria */}).limit(1).size(); 同步吗?
.count(with_limit_and_skip=True)。没有方法叫.size()
我不相信有直接的方法可以通过它的价值来检查项目的存在。但是您可以通过仅检索 id (with field selection) 来做到这一点
db.your_collection.find({..criteria..}, {"_id" : 1});
【讨论】:
findOne 超过 find
从Mongo 2.6开始,count 有一个limit 可选参数,这使它成为查找文档是否存在的可行替代方案:
db.collection.count({}, { limit: 1 })
// returns 1 if exists and 0 otherwise
或使用过滤查询:
db.collection.count({/* criteria */}, { limit: 1 })
限制匹配出现的次数会使集合扫描在找到匹配项时停止,而不是遍历整个集合。
从Mongo 4.0.3开始,因为count()是considered deprecated,我们可以用countDocuments代替:
db.collection.countDocuments({}, { limit: 1 })
或使用过滤查询:
db.collection.countDocuments({/* criteria */}, { limit: 1 })
【讨论】:
使用 find() + limit() 明显更快,因为 findOne() 如果存在,将始终读取 + 返回文档。查找()只是 返回游标(或不返回)并且仅在迭代时读取数据 通过光标。
db.collection.find({_id: "myId"}, {_id: 1}).limit(1)
(而不是db.collection.findOne({_id: "myId"}, {_id: 1}))。
查看更多详情:Checking if a document exists – MongoDB slow findOne vs find
【讨论】:
find() 将始终返回一个光标(即使文档不存在 - 在这种情况下 hasNext() 将返回 false。
filter_dict = {"key":value}
if db.collection.count_documents(filter_dict):
print("item is existed")
else:
print("item is not existed")
【讨论】:
Xavier 回答的更新:
db.collection.countDocuments({}, { limit: 1 })
现在将回调作为第二个参数,因此可以使用它来代替:
db.collection.countDocuments({}).limit(1)
【讨论】:
我目前正在使用这样的东西:
async check(query) {
const projection = { _id: 1 };
return !!db.collection.findOne(query, projection);
}
它会返回真或假,当然只返回 _id: 1 用于最小的数据传输。
【讨论】:
我很惊讶这里没有提到 $exists operator。
db.collection.findOne({myFieldName: {$exists: 1}})
如果你想要相反的(找到一个字段不存在的地方):
db.collection.findOne({myFieldName: {$exists: 0}})
如果你想得到一个光标,使用find() instad of findOne(),你可以用db.collection.find({myFieldName: {$exists: 1}}).isExhausted()得到一个布尔值
请注意,isExhausted() 仅是 mongo shell method
【讨论】:
我只是简单地使用了 lodash 框架 - _isEmpty();
const {
MongoClient,
ObjectId
} = require('mongodb');
const _ = require('lodash');
MongoClient.connect(testURL, {
useNewUrlParser: true
}, (err, client) => {
let db = client.db('mycompany');
if (err) {
console.log('unable to connect to the mycompany database');
} else {
console.log('test connection to the database');
};
db.collection('employee').find({
name: 'Test User'
}).toArray((err, result) => {
if (err) {
console.log('The search errored');
} else if (_.isEmpty(result)) {
console.log('record not found')
} else {
console.log(result);
};
});
client.close();
});
【讨论】:
result.length === 0,为什么还要使用框架?
如果你使用 Java 和 Spring,你可以使用它:
public interface UserRepository extends MongoRepository<User, ObjectId> {
boolean existsByUsername(String username);
}
它对我有用。
【讨论】: