您如何在Mongo中查询“不为空”?


Answers:


812

这将返回所有带有名为“ IMAGE URL”的键的文档,但是它们可能仍为空值。

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

这将返回所有带有称为“ IMAGE URL”的键非空值的文档。

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

另外,根据文档,$ exists当前不能使用索引,但是$ ne可以使用。

编辑:由于对此答案感兴趣,添加了一些示例

鉴于这些插入:

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

这将返回所有三个文档:

db.test.find();

这将仅返回第一个和第二个文档:

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

这将仅返回第一个文档:

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

这将仅返回第二个和第三个文档:

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

12
根据文档,$ne 包括不包含字段的文档。自您发布答案以来,这种情况发生了变化吗?docs.mongodb.org/manual/reference/operator/query/ne
Andrew Mao

2
我不相信这已经改变。在检查$ ne时,会在所有文档中检查该值,包括那些不包含该字段的文档,但是$ ne:null仍将不匹配不包含该字段的文档,因为该字段的值仍为null,即使该文档中不存在该字段。
蒂姆·高

2
您如何匹配第二个文档?
BT

1
@River我三年前写这本书时检查了一下,为了确定,我刚刚安装了Mongo并再次尝试了一下。它仍然以相同的方式工作,答案是正确的。从倒数第二个查询仅返回第一个文档。
蒂姆·高

1
给出的示例使如何使用它变得可以理解。:-)
Eric Dela Cruz

92

一支班轮最好:

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

这里,

mycollection:放置所需的收藏名称

fieldname:放置所需的字段名称

说明:

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

$ ne选择字段值不等于指定值的文档。这包括不包含该字段的文档。

因此,在您提供的情况下,以下查询将返回具有imageurl字段的所有文档,并且这些文档的值不为null:

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

11
$exists: true是多余的,$ne: null足够了。
Stanislav Karakhanov '18

这应该是最好的答案。$exists: true也返回null值。必须同时存在$exists: true$ne: null。这不是多余的。
Ismail Kattakath

47

在pymongo中,您可以使用:

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

因为pymongo将mongo“ null”表示为python“ None”。


18
db.collection_name.find({"filed_name":{$exists:true}});

提取包含此filed_name的文档,即使它为null。

我的主张:

db.collection_name.find({"field_name":{$type:2}}) //type:2 == String

您可以检查所需属性的类型,它将返回所查询的field_name包含值的所有文档,因为您正在检查文件的类型,否则,如果它为null,则类型条件不匹配,因此将不返回任何内容。

Nb:如果field_name有一个空字符串,表示“”,则将返回它。

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

额外验证:

好的,我们还没有完成,还需要一个额外的条件。

db.collection_name.
find({ "field_name":{$type:2},$where:"this.field_name.length >0"})

要么

db.collection_name.
find({ "field_name":{$ne:null},$where:"this.field_name.length >0"})

参考




4

在理想情况下,您想测试所有三个null“”(记录中不存在该字段)

您可以执行以下操作。

db.users.find({$and: [{"name" : {$nin: ["", null]}}, {"name" : {$exists: true}}]})

3

尚未提及的替代方法,但是对于某些方法(不适用于NULL条目)可能是更有效的选择,即使用稀疏索引(仅当字段中存在某些内容时,索引中的条目才会存在)。这是一个示例数据集:

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 }

现在,在imageUrl字段上创建稀疏索引:

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

现在,总是有一个机会(尤其是像我的示例这样的小数据集)有一个机会,而不是使用索引,MongoDB将使用表扫描,甚至用于潜在的覆盖索引查询。事实证明,这为我提供了一种简单的方法来说明此处的区别:

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" }
{  }
{  }

好的,因此将imageUrl返回没有的多余文档,只是空的,而不是我们想要的。只是为了确认原因,请解释一下:

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
}

因此,是的,a BasicCursor等于表扫描,它不使用索引。让我们强制查询将稀疏索引与一起使用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" }

我们一直在寻找结果-仅返回填充字段的文档。这也仅使用索引(即它是一个覆盖的索引查询),因此只有索引需要在内存中才能返回结果。

这是一个特殊的用例,不能普遍使用(有关这些选项,请参见其他答案)。特别要注意的是,按照目前的情况,您不能count()以这种方式使用(例如,我将返回6而不是4),因此请仅在适当时使用。


文本字段始终是稀疏索引,您不必显式指定。只是我的2美分。
alianos-

3

检查mongo罗盘中列是否存在的最简单方法是:

{ 'column_name': { $exists: true } }

1
这样做的问题是,它假定该字段真正从未被持久保存,但是OP似乎(从标题来看)表明它可以存在,但显式设置为null。
Carighan

-10

查询将是

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

它将返回所有以“ IMAGE URL”作为键的文档.....


1
@kilianc不是这样。$ exists也将捕获空值。参见docs.mongodb.org/manual/reference/operator/query/exists
dorvak

正是@dorvak,这就是为什么这不能满足问题中的用例的原因。
kilianc '16

这个答案是错误的,因为$exists检查密钥"IMAGE URL"并且不考虑它的值(null),并将返回带有的文档"IMAGE URL" : null
大卫·哈里里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.