按Mongodb中的嵌入式对象值排序 [英] sort by embedded object value in Mongodb
问题描述
我有一个这样的架构:
{
tags:[
{
id:"t1",
score:70
},
{
id:"t1",
score:60
}
]
}
我想对tag.id搜索上的查询进行排序,以按照相应的分数进行排序.因此,如果我搜索db.collection.find({tags.id:"t1"}).sort({tags.score:-1}),它是按"t1"对象的得分而不是其他标签进行排序的.
有什么建议吗?
如果您需要在运行时计算出类似的结果,并使用数组中的已过滤"内容确定排序顺序,那么最好使用 在管道的第一部分用于将数组内容预过滤"(以及保留原始字段)为ID等于"t1"的"score"值.这是通过处理 将数组缩小并调整为值后,您可以处理 然后,只需应用 当然要在开始处添加一个 计算的替代方法是在将条目写入文档中的数组时执行所有操作.有点凌乱,但它是这样的: 此处仅 这当然可以为文档添加各种其他属性,但是最终结果是大大简化了排序: 它的运行速度比使用聚合管道进行计算要快得多. 因此请考虑设计原则.要在其中过滤和配对结果以进行排序的数组中的结构化数据,意味着在运行时进行计算以确定要对哪个值进行排序.在 I have a schema like this: I want to sort the query on tag.id search to get sorted by the corresponding score. So if I search db.collection.find({tags.id:"t1"}).sort({tags.score:-1}) , it sorted by score of the "t1" object not other tags. Any suggestion? If you need to calculate out something like this at runtime, with "filtered" content from the array determining the sort order, then you best do something with Where the first part of the pipeline is used to "pre-filter" the array content ( as well as keeping the original field ) to just those values of "score" where the id is equal to "t1". This is done by processing The With the array reduced and reshaped to values you process Then it is just a matter of applying the Of course add a The alternate to calculating is to do it all as you write entries to the array in the documents. Kind of messy, but it goes something like this: Here the This would of course have the effect of adding various additional properties to the documents, but the end result is sorting is greatly simplified: And it's going to run a lot faster than calculating with an aggregation pipeline. So consider the design principles. Structured data in arrays where you want filtered and paired results for sorting means calculating at run-time to determine which value to sort on. Adding additional properties to the document on 这篇关于按Mongodb中的嵌入式对象值排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!db.collection.aggregate([
// Pre-filter the array elements
{ "$project": {
"tags": 1,
"score": {
"$setDifference": [
{ "$map": {
"input": "$tags",
"as": "tag",
"in": {
"$cond": [
{ "$eq": [ "$$el.id", "t1" ] },
"$$el.score",
false
]
}
}},
[false]
]
}
}},
// Unwind to denormalize
{ "$unwind": "$score" },
// Group back the "max" score
{ "$group": {
"_id": "$_id",
"tags": { "$first": "$tags" },
"score": { "$max": "$score" }
}},
// Sort descending by score
{ "$sort": { "score": -1 } }
])
$map
来完成的.元素通过 $cond
来确定是否返回分数"该元素或false
.$setDifference
操作与单个操作进行了比较元素数组[false]
,可有效删除从$map
返回的所有false
值.作为一个集合",它还会删除重复的条目,但是出于排序目的,这是一件好事.$unwind
准备在下一阶段将这些值作为单个元素处理. $group
阶段实际上适用于 $max
,以返回过滤结果中包含的最大值.>
$sort
在确定的值上订购文件.当然,如果您想以其他方式使用它,请使用 $min
并按升序排序.$match
阶段如果您只想要真正包含标签中id
的"t1"值的文档.但这部分与您要获得的过滤结果的排序无关.
db.collection.update(
{ "_id": docId },
{
"$push": { "tags": { "id": "t1", "score": 60 } },
"$max": { "maxt1score": 60 },
"$min": { "mint1score": 60 }
}
)
$max
更新运算符设置如果新值大于现有值,则为指定字段的值,否则不存在任何属性.对于 $min
,情况恰好相反如果小于此值将被新值替换.
db.collection.find().sort({ "maxt1score": -1 })
.update()
上向文档添加其他属性意味着您可以简单地引用这些属性以直接对结果进行排序.{
tags:[
{
id:"t1",
score:70
},
{
id:"t1",
score:60
}
]
}
.aggregate()
to reshape and determine a sort value like this:db.collection.aggregate([
// Pre-filter the array elements
{ "$project": {
"tags": 1,
"score": {
"$setDifference": [
{ "$map": {
"input": "$tags",
"as": "tag",
"in": {
"$cond": [
{ "$eq": [ "$$el.id", "t1" ] },
"$$el.score",
false
]
}
}},
[false]
]
}
}},
// Unwind to denormalize
{ "$unwind": "$score" },
// Group back the "max" score
{ "$group": {
"_id": "$_id",
"tags": { "$first": "$tags" },
"score": { "$max": "$score" }
}},
// Sort descending by score
{ "$sort": { "score": -1 } }
])
$map
which applies a condition to each element via $cond
to determine whether to return the "score" for that element or false
.$setDifference
operation does a comparison to a single element array [false]
which effectively removes any false
values returned from the $map
. As a "set", this also removes duplicate entries, but for the sort purpose here this is a good thing.$unwind
ready for the next stage to deal with the values as individual elements. The $group
stage essentially applies $max
on the "score" to return the highest value contained in the filtered results.$sort
on the determined value to order the documents. Naturaly if you wanted this the other way around then use $min
and sort in ascending order instead.$match
stage to the beginning if all you really want is documents that actually contain "t1" values for id
within the tags. But that part is of least relevance to the sorting on filtered results you want to achieve.db.collection.update(
{ "_id": docId },
{
"$push": { "tags": { "id": "t1", "score": 60 } },
"$max": { "maxt1score": 60 },
"$min": { "mint1score": 60 }
}
)
$max
update operator only sets the value for the specified field if the new value is greater than the existing value or otherwise no property yet exists. The reverse case is true of $min
, where only if less than it will be replaced with the new value.db.collection.find().sort({ "maxt1score": -1 })
.update()
means you can simply reference those properties in order to directly sort results.