如何使用mongodb中的条件获取数组的最后一个元素。我无法使用切片。这是我的代码
{ "1" : { "relevancy" : [ "Y" ] }, "_id" : ObjectId("530824b95f44eac1068b45c0") }
{ "1" : { "relevancy" : [ "Y", "Y" ] }, "_id" : ObjectId("530824b95f44eac1068b45c2") }
{ "1" : { "relevancy" : [ "N" ] }, "_id" : ObjectId("530824b95f44eac1068b45c3") }
{ "1" : { "relevancy" : [ "Y", "Y" ] }, "_id" : ObjectId("530824b95f44eac1068b45c4") }
{ "1" : { "relevancy" : [ "Y", "N" ] }, "_id" : ObjectId("530824b95f44eac1068b45c6") }
{ "1" : { "relevancy" : [ "N" ] }, "_id" : ObjectId("530824b95f44eac1068b45c7") }
{ "1" : { "relevancy" : [ "Y", "N" ] }, "_id" : ObjectId("530824b95f44eac1068b45c8") }
我想计算具有“Y”的行数作为数组“相关性”的最后一个元素。从上面的代码应该是3.如何做到这一点。请帮助我。
答案 0 :(得分:15)
正如您现在所知,$slice仅用于投影以限制结果中返回的数组元素。因此,您将无法使用find()的结果以编程方式处理列表。
更好的方法是使用aggregate。但首先让我们考虑如何使用 $ slice :
> db.collection.find({},{ relevancy: {$slice: -1} })
{ "_id" : ObjectId("530824b95f44eac1068b45c0"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c2"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c3"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c4"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c6"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c7"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c8"), "relevancy" : [ "N" ] }
所以你得到了最后一个数组元素,但是由于你不能匹配最后一个元素值,你很难循环结果。您也可以在代码中完成此操作。
现在让我们看一下聚合:
db.collection.aggregate([
// Match things so we get rid of the documents that will never match, but it will
// still keep some of course since they are arrays, that *may* contain "N"
{ "$match": { "relevancy": "Y" } },
// De-normalizes the array
{ "$unwind": "$relevancy" },
// The order of the array is retained, so just look for the $last by _id
{ "$group": { "_id": "$_id", "relevancy": { "$last": "$relevancy" } }},
// Match only the records with the results you want
{ "$match": { "relevancy": "Y" }},
// Oh, and maintain the original _id order [ funny thing about $last ]
{ "$sort": { "_id": 1 } }
])
即使这是你第一次使用aggregate(),我也鼓励你学习。它可能是您最有用的问题解决工具。当然一直适合我。如果您正在学习,请将每个步骤一次放入一次。
在您的文档表单上也不确定,所有1: { ... }
子文档符号似乎都是错误的,但您应该清除或调整上面的代码以引用"1.relevancy"
。我希望你的文件看起来更像这样:
{ "relevancy" : [ "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c0") }
{ "relevancy" : [ "Y", "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c2") }
{ "relevancy" : [ "N" ], "_id" : ObjectId("530824b95f44eac1068b45c3") }
{ "relevancy" : [ "Y", "Y" ], "_id" : ObjectId("530824b95f44eac1068b45c4") }
{ "relevancy" : [ "Y", "N" ], "_id" : ObjectId("530824b95f44eac1068b45c6") }
{ "relevancy" : [ "N" ], "_id" : ObjectId("530824b95f44eac1068b45c7") }
{ "relevancy" : [ "Y", "N" ], "_id" : ObjectId("530824b95f44eac1068b45c8") }
当然,MongoDB 3.2引入了$slice
的“聚合”运算符和更好的$arrayElemAt
运算符,无需进行任何$unwind
和$group
处理。在初始$match
查询后,您只需与$redact
进行“逻辑匹配”:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
在决定是否$$KEEP
或$$PRUNE
返回结果中的文档时,将对数组的最后一个元素进行检查。
如果您仍想要“投影”,那么您实际上可以添加$slice
:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } }
])
或替代方法:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } },
{ "$match": { "relevancy": "Y" } }
])
但是首先执行$redact
并且“然后”在$ $项目中进行任何重新塑造可能成本更低。
答案 1 :(得分:0)
从Mongo 4.4
开始,聚合运算符$last
可用于访问数组的最后一个元素:
// { "1": { "relevancy": ["Y"] } }
// { "1": { "relevancy": ["Y", "Y"] } }
// { "1": { "relevancy": ["N"] } }
// { "1": { "relevancy": ["Y", "Y"] } }
// { "1": { "relevancy": ["Y", "N"] } }
// { "1": { "relevancy": ["N"] } }
// { "1": { "relevancy": ["Y", "N"] } }
db.collection.aggregate([
{ $project: { last: { $last: "$1.relevancy" } } },
// { "last": "Y" }
// { "last": "Y" }
// { "last": "N" }
// { "last": "Y" }
// { "last": "N" }
// { "last": "N" }
// { "last": "N" }
{ $match: { "last": "Y" } },
// { "last": "Y" }
// { "last": "Y" }
// { "last": "Y" }
{ $count: "result" }
// { "result" : 3 }
])