Mongo:查找没有特定字段的项

132
如何在MongoDB中搜索缺少某个字段的集合中的文档?
3个回答

199

是的,可以使用$exists

db.things.find( { a : { $exists : false } } ); // return if a is missing

当 为 true 时,$exists 匹配包含该字段的文档,包括字段值为 null 的文档。如果 为 false,则查询仅返回不包含该字段的文档。

当 为 true 时,$exists 匹配包含该字段的文档,包括字段值为 null 的文档。如果 为 false,则查询仅返回不包含该字段的文档。


2
请注意,$exist 查询无法使用索引(请参见http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24exists)。 - Theo
4
从MongoDB 2.0开始,$exists可以利用索引(https://jira.mongodb.org/browse/SERVER-393)。 - Dmitry Schetnikovich
我需要这个东西来在 Mongoid 中使用作为一个范围。看起来是这样的 > scope :without_recommendation, :where => {:recommendation => {"$exists"=>false}} - genkilabs

60

如果您不在意字段是否缺失或null(或者它从未为null),那么您可以使用稍微更短、更安全的方法:and

db.things.find( { a : null } ); // return if a is missing or null

这样更安全,因为即使字段为null,$exists也会返回true ,而这通常不是期望的结果,可能会导致NPE。


2
然而,阅读代码的人可能会将其解释为该字段必须等于“null”而不是缺失。这实际上是意外的行为,因为您无法对“0”(也是“false”)执行相同的操作,因此“null”在这里有点例外。因此,最佳做法是使用 $exists: false 更易读的答案,这样就不会产生歧义。请记住,如果您需要在其后添加注释,则稍微缩短的变体实际上并不更短! - Yeti
1
@Yeti 如果我的目标是查找所有缺少字段a值的对象,无论是因为anull还是因为a丢失,那么$exists就不够好了,因为它无法捕获anull的情况。 - nilskp
我认为这是最好的答案,因为 { $exists: false } 如果有索引也不会使用它,但是如果有一个索引,{ $eq: false } 将会使用它。 - Alex Jones

2
仅供参考,在使用mongoose(v6)并尝试使用$exists查找mongoose模式中未定义的字段时,mongoose v6会对其进行转义。
请参见此处https://mongoosejs.com/docs/migrating_to_6.html#strictquery-is-removed-and-replaced-by-strict 例如:
const userSchema = new Schema({ name: String });
const User = mongoose.model('User', userSchema);

// By default, this is equivalent to `User.find()` because Mongoose filters out `notInSchema`
await User.find({ notInSchema: 1 });

// Set `strictQuery: false` to opt in to filtering by properties that aren't in the schema
await User.find({ notInSchema: 1 }, null, { strictQuery: false });
// equivalent:
await User.find({ notInSchema: 1 }).setOptions({ strictQuery: false });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接