问题是下一个问题:
Get documents with tags in list, ordered by total number of matches
但是他们说使用聚合框架是可能的,这是可能的吗?
答案 0 :(得分:6)
是的,可以使用聚合框架。
<强>假设强>
tags
属性是一个集合(没有重复的元素)查询
这种方法会强制您展开结果并使用未展开的结果重新评估匹配谓词,因此效率非常低。
db.test_col.aggregate(
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$unwind: "$tags"},
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$group: {
_id:{"_id":1},
matches:{$sum:1}
}},
{$sort:{matches:-1}}
);
预期结果
{
"result" : [
{
"_id" : {
"_id" : ObjectId("5051f1786a64bd2c54918b26")
},
"matches" : 3
},
{
"_id" : {
"_id" : ObjectId("5051f1726a64bd2c54918b24")
},
"matches" : 2
},
{
"_id" : {
"_id" : ObjectId("5051f1756a64bd2c54918b25")
},
"matches" : 1
}
],
"ok" : 1
}
答案 1 :(得分:0)
使用 $ size 和 $ setIntersection 可以有效解决此问题,而不会引起内存倍增。
tagList = ['shirt', 'cotton', 'black']
db.test_col.aggregate(
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$project:
{"title":1,"tags":1},
{$order:
{"$size":
{"$setIntersection": [ tagList, "$tags" ]}},
{$sort:{order:-1}}
);
首先,我们匹配至少具有一个元素匹配的文档。
然后,我们投影所需的键/列以及新的订单键/列。通过获取“ db中的标签”和“查询中的标签”之间相交元素的数量来生成顺序。
然后我们以降序进行简单排序。 这对我有用。 回答了here
的类似问题