use*_*354 11 mongodb mongodb-query aggregation-framework
如何使用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") }
Run Code Online (Sandbox Code Playgroud)
我想计算具有"Y"的行数作为数组"相关性"的最后一个元素.从上面的代码应该是3.如何做到这一点.请帮助我.
Nei*_*unn 16
正如您现在所知,$ slice仅用于投影以限制结果中返回的数组元素.因此,您将无法使用find()的结果以编程方式处理列表.
更好的方法是使用聚合.但首先让我们考虑如何使用$ 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" ] }
Run Code Online (Sandbox Code Playgroud)
因此,您获得了最后一个数组元素,但由于无法匹配最后一个元素值,因此您无法循环结果.您也可以在代码中完成此操作.
现在让我们来看看聚合:
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 } }
])
Run Code Online (Sandbox Code Playgroud)
即使这是你第一次使用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") }
Run Code Online (Sandbox Code Playgroud)
当然,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"
}
}}
])
Run Code Online (Sandbox Code Playgroud)
这将在决定是否$$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 ] } } }
])
Run Code Online (Sandbox Code Playgroud)
或者替代方法:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } },
{ "$match": { "relevancy": "Y" } }
])
Run Code Online (Sandbox Code Playgroud)
但是$redact第一次做的成本可能更低,"然后"在$ $项目中进行任何重新塑造.