使用聚合在Mongodb中的复杂条件中排序

编程入门 行业动态 更新时间:2024-10-25 04:19:03
本文介绍了使用聚合在Mongodb中的复杂条件中排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我创建一个关于使用$ match的问题已经解决了,但现在我被困在一个更复杂的例子。例如,考虑我的Json的结构:

{ user:'bruno', :[ {id:0,value:3.5}, {id:1,value:hello} ] }

我想添加或排序,对'value'中包含的值只应用标识符'id'等于0的一些变换例如排序方法。

考虑以下数据:

db .my_collection.insert({user:'bruno',answers:[{id:0,value:3.5},{id:1,value:hello}]}) db.my_collection .insert({user:'bruno2',answers:[{id:0,value:0.5},{id:1,value:world}]}) pre>

我尝试使用:

db.my_collection.aggregate {$ sort:{answers:{$ elemMatch:{id:0,value:-1}}}})

但是,它没有工作。预期的结果是: {user:'bruno2'answers:[{id:0,value:0.5},{id:1,value:world}]}, {user: bruno的答案:[{id:0,value:3.5},{id:1,value:hello}]})

谢谢。 >

解决方案

首先,请注意,您的排序示例格式错误:聚合方法使用数组作为输入,其中数组中的每个元素都指定一个阶段在聚合管道中。另请注意, $ elemMatch 运算符不能用作$ sort阶段的一部分。

一个方法来实现你想要做的排序的例子是使用聚合框架的 $ unwind 管道操作符。展开数组会将数组元素逐个分离成单独的文档。例如,以下查询

db.my_collection.aggregate([{$ unwind:$ answers}]);

返回如下所示的内容:

[ {_id:ObjectId(5237157f3fac8e36fdb0b96e),user:bruno,answers {id:0,value:3.5 } }, {_id:ObjectId(5237157f3fac8e36fdb0b96e) ,user:bruno,answers:{id:1,value:hello} $ b}, {_id:ObjectId(523715813fac8e36fdb0b96f),user:bruno2,answers:{ id:0,value:0.5 } }, {_id:ObjectId(523715813fac8e36fdb0b96f), user:bruno2,answers:{id:1,value:world} } $ b b]

添加$ match阶段将允许您仅抓取answer.id为零的文档。最后,$ sort阶段允许你按answers.value排序。汇总查询是:

db.my_collection.aggregate([ {$ unwind:$ answers }, {$ match:{answers.id:0}}, {$ sort:{answers.value:-1}} ]

输出:

[ {_id:ObjectId(5237157f3fac8e36fdb0b96e),user:bruno,answers:{id:0,value:3.5 } }, {_id:ObjectId(523715813fac8e36fdb0b96f),user:bruno2,answers:{id:0,value:0.5 } } b $ b]

根据你的要求, $ unwind甚至聚合框架。如果相反,你想找到answer.id等于0和answers.value等于3.5的文档,然后将answers.value更改为4,你可以使用find with $ elemMatch,然后是db.collection.save():

doc = db.my_collection.findOne({answers:{$ elemMatch:{id:0,value: 3.5}}}); for(i = 0; i< doc.answers.length; i ++){ if(doc.answers [i] .id === 0){ doc.answers [i ] .value = 4; db.my_collection.save(doc); break; } }

I create a topic about using $match which was solved, but now I'm stuck in a more complex example. For example, consider the struct of my Json:

{ user: 'bruno', answers: [ {id: 0, value: 3.5}, {id: 1, value: "hello"} ] }

I would like to add or order, apply some transformations on the values contained in 'value' only the identifier 'id' equal to 0, for example a sort method.

Consider the following data:

db.my_collection.insert({ user: 'bruno', answers: [ {id: 0, value: 3.5}, {id: 1, value: "hello"}]}) db.my_collection.insert({ user: 'bruno2', answers: [ {id: 0, value: 0.5}, {id: 1, value: "world"}]})

I tried using:

db.my_collection.aggregate ({$sort: {"answers": {"$elemMatch": {id: 0, value: -1}}}})

But, it didn't work. The expected result was: {user: 'bruno2' answers: [{id: 0, value: 0.5}, {id: 1, value: "world"}]}, {user: 'bruno' answers: [{id: 0, value: 3.5}, {id: 1, value: "hello"}]})

Thank you.

解决方案

First, note that your sort example is malformed: the aggregate method takes an array as input, where each element in the array specifies a stage in an aggregation pipeline. Also, note that the $elemMatch operator cannot be used as part of a $sort stage.

One way to achieve what you're trying to do with your sort example is use the aggregation framework's $unwind pipeline operator. Unwinding an array will peel the array elements off one-by-one into separate documents. For example, the following query

db.my_collection.aggregate([ {$unwind: "$answers"} ]);

returns something like the following:

[ { "_id" : ObjectId("5237157f3fac8e36fdb0b96e"), "user" : "bruno", "answers" : { "id" : 0, "value" : 3.5 } }, { "_id" : ObjectId("5237157f3fac8e36fdb0b96e"), "user" : "bruno", "answers" : { "id" : 1, "value" : "hello" } }, { "_id" : ObjectId("523715813fac8e36fdb0b96f"), "user" : "bruno2", "answers" : { "id" : 0, "value" : 0.5 } }, { "_id" : ObjectId("523715813fac8e36fdb0b96f"), "user" : "bruno2", "answers" : { "id" : 1, "value" : "world" } } ]

Adding a $match phase will allow you to grab only the documents where answers.id is zero. Finally, a $sort phase allows you to sort by answers.value. All together the aggregation query is:

db.my_collection.aggregate([ {$unwind: "$answers"}, {$match: {"answers.id": 0}}, {$sort: {"answers.value": -1}} ]);

And the output:

[ { "_id" : ObjectId("5237157f3fac8e36fdb0b96e"), "user" : "bruno", "answers" : { "id" : 0, "value" : 3.5 } }, { "_id" : ObjectId("523715813fac8e36fdb0b96f"), "user" : "bruno2", "answers" : { "id" : 0, "value" : 0.5 } } ]

Based on what your asking, it doesn't sound like you'll always need $unwind or even the aggregation framework. If instead you wanted to find the document with answers.id equal to 0 and answers.value equal to 3.5, and then change answers.value to 4 you could use find with $elemMatch followed by db.collection.save():

doc = db.my_collection.findOne({"answers": {$elemMatch: {"id": 0, "value": 3.5}}}); for (i=0; i<doc.answers.length; i++) { if (doc.answers[i].id === 0) { doc.answers[i].value = 4; db.my_collection.save(doc); break; } }

更多推荐

使用聚合在Mongodb中的复杂条件中排序

本文发布于:2023-11-22 20:54:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1618984.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:条件   Mongodb

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!