查询数组大小大于1的文档

我有一个MongoDB集合,其中包含以下格式的文档:

{"_id" : ObjectId("4e8ae86d08101908e1000001"),"name" : ["Name"],"zipcode" : ["2223"]}{"_id" : ObjectId("4e8ae86d08101908e1000002"),"name" : ["Another ", "Name"],"zipcode" : ["2224"]}

我目前可以获取匹配特定数组大小的文档:

db.accommodations.find({ name : { $size : 2 }})

这将正确返回name数组中包含2个元素的文档。但是,我不能执行$gt命令来返回name字段数组大小大于2的所有文档:

db.accommodations.find({ name : { $size: { $gt : 1 } }})

如何选择大小大于1的name数组的所有文档(最好不必修改当前数据结构)?

641532 次浏览

更新时间:

对于mongoDB版本2.2+更有效的方法来做到这一点,由@JohnnyHK在另一个中描述


  1. 使用$在哪里

    db.accommodations.find({$where:"this.name.length>1"});

可是…

Javascript的执行速度比上面列出的本机运算符慢此页面,但非常灵活。请参阅服务器端处理页面更多信息

  1. 创建额外字段NamesArrayLength,使用名称数组长度更新它,然后在查询中使用:

    db.accommodations.find({"NamesArrayL":{$gt: 1}});

这将是更好的解决方案,并且会更快地工作(您可以在其上创建索引)。

我相信这是回答您问题的最快查询,因为它不使用解释的$where子句:

{$nor: [{name: {$exists: false}},{name: {$size: 0}},{name: {$size: 1}}]}

它的意思是“除了没有名称(不存在或空数组)或只有一个名称的所有文档”。

测试:

> db.test.save({})> db.test.save({name: []})> db.test.save({name: ['George']})> db.test.save({name: ['George', 'Raymond']})> db.test.save({name: ['George', 'Raymond', 'Richard']})> db.test.save({name: ['George', 'Raymond', 'Richard', 'Martin']})> db.test.find({$nor: [{name: {$exists: false}}, {name: {$size: 0}}, {name: {$size: 1}}]}){ "_id" : ObjectId("511907e3fb13145a3d2e225b"), "name" : [ "George", "Raymond" ] }{ "_id" : ObjectId("511907e3fb13145a3d2e225c"), "name" : [ "George", "Raymond", "Richard" ] }{ "_id" : ObjectId("511907e3fb13145a3d2e225d"), "name" : [ "George", "Raymond", "Richard", "Martin" ] }>

在MongoDB 2.2+中有一种更有效的方法来做到这一点,现在您可以在查询对象键中使用数字数组索引(基于0)。

// Find all docs that have at least two name array elements.db.accommodations.find({'name.1': {$exists: true}})

您可以使用使用部分过滤器表达式的索引支持此查询(需要3.2+):

// index for at least two name array elementsdb.accommodations.createIndex({'name.1': 1},{partialFilterExpression: {'name.1': {$exists: true}}});

以上都不适合我。这一个做到了,所以我分享它:

db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )

你也可以使用聚合:

db.accommodations.aggregate([{$project: {_id:1, name:1, zipcode:1,size_of_name: {$size: "$name"}}},{$match: {"size_of_name": {$gt: 1}}}])

//将“size_of_name”添加到传输文档并使用它来过滤名称的大小

db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})

试着做这样的事情:

db.getCollection('collectionName').find({'ArrayName.1': {$exists: true}})

1是数字,如果要获取大于50的记录,请执行ArrayName.50谢谢!

我找到了这个解决方案,找到数组字段大于一定长度的项目

db.allusers.aggregate([{$match:{username:{$exists:true}}},{$project: { count: { $size:"$locations.lat" }}},{$match:{count:{$gt:20}}}])

第一个$Match聚合使用一个对所有文档都为真的参数。如果为空,我会得到

"errmsg" : "exception: The argument to $size must be an Array, but was of type: EOO"

虽然上面的答案都有效,但你最初尝试做的是正确的方法,但是你只是语法向后(切换“$size”和“$gt”)。

更正:

db.collection.find({items: {$gt: {$size: 1}}})

可以使用$exr(3.6mongo版本运算符)在常规查询中使用聚合函数。

比较query operators vsaggregation comparison operators

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})

MongoDB 3.6包含$exrhttps://docs.mongodb.com/manual/reference/operator/query/expr/

您可以使用$extr来计算$匹配中的表达式,或者查找。

{ $match: {$expr: {$gt: [{$size: "$yourArrayField"}, 0]}}}

或找到

collection.find({$expr: {$gte: [{$size: "$yourArrayField"}, 0]}});

您可以通过MongoDB聚合来完成任务:

db.collection.aggregate([{$addFields: {arrayLength: {$size: '$array'}},},{$match: {arrayLength: {$gt: 1}},},])