[英]How to Sort by Weighted Values
我有一个问题,我想根据另一个集合的字段值对查询结果进行排序,
问题:我想首先让用户获得123个朋友,然后获取他们的帖子,然后使用朋友的强度值对帖子进行排序,
我有这个 :
POST COLLECTON:
{
user_id: 8976,
post_text: 'example working',
}
{
user_id: 673,
post_text: 'something',
}
USER COLLECTON:
{
user_id: 123,
friends: {
{user_id: 673,strength:4}
{user_id: 8976,strength:1}
}
}
根据您从用户中检索到的信息,您实际上希望进行如下所示的聚合框架查询:
db.posts.aggregate([
{ "$match": { "user_id": { "$in": [ 673, 8976 ] } } },
{ "$project": {
"user_id": 1,
"post_text": 1,
"weight": {
"$cond": [
{ "$eq": [ "$user_id", 8976 ] },
1,
{ "$cond": [
{ "$eq": [ "$user_id", 673 ] },
4,
0
]}
]
}
}},
{ "$sort": { "weight": -1 } }
])
那么为什么不聚合就聚合呢? 如您所见,聚合框架所做的不仅仅是聚合。 在这里,它用于将新字段“投影”到文档中,并用“权重”进行填充。 这使您可以按希望排序结果的值将结果重新排序。
当然,您需要以一种对所有数据所做的“生成的”方式,将初始数据从原始数据转换为该表单。 这需要几个步骤,但是在这里,我将介绍实现它的JavaScript方法,该方法应该很容易转换为大多数语言
还要假设您的实际“用户”看起来更像这样,这将是有效的:
{
"user_id": 123,
"friends": [
{ "user_id": 673, "strength": 4 },
{ "user_id": 8976, "strength": 1 }
]
}
从这样的对象中,然后构造聚合管道:
// user is the structure shown above
var stack = [];
args = [];
user.friends.forEach(function(friend) {
args.push( friend.user_id );
var rec = {
"$cond": [
{ "$eq": [ "user_id", friend.user_id ] },
friend.strength
]
};
if ( stack.length == 0 ) {
rec["$cond"].push(0);
} else {
var last = stack.pop();
rec["$cond"].push( last );
}
stack.push( rec );
});
var pipeline = [
{ "$match": { "user_id": { "$in": args } } },
{ "$project": {
"user_id": 1,
"post_text": 1,
"weight": stack[0]
}},
{ "$sort": { "weight": -1 } }
];
db.posts.aggregate(pipeline);
这就是全部。 现在,您有了一些代码,可以浏览用户的“朋友”列表,并构造另一个查询,以从每个朋友的“强度”值加权得到这些朋友的所有帖子。
当然,通过删除或更改$match
,您可以通过查询所有帖子来做几乎相同的事情,但是保持“权重”投射可以将所有“朋友”帖子“浮动”到顶部。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.