考虑以下集合,我们称之为things
。它有很多文件
{ _id: 'aaa', foo: 82374 },
{ _id: 'bbb', foo: 32476 },
{ _id: 'ccc', foo: 25733 },
{ _id: 'ddd', foo: 45253 },
{ _id: 'eee', foo: 15545 }
我需要找到所有匹配_id
的子集的文档,这些文档我已经知道并满足其他一些条件。
此外,我希望那些在_id
上匹配的文档首先出现在排序顺序中,其余文档则由其他字段排序。
不幸的是,我不能简单地找到匹配的_id
,因为things
包含数以万计的文档,我需要skip
和limit
结果。这导致了一个丑陋,混乱和复杂的应用程序级别连接。
理想情况下,我想要的是:
var query = {
$or: [
{ _id: { $in: ['bbb', 'ddd'] } },
{ foo: { $lt: 20000 } }
]
};
var sort = {
// somehow make the _id take priority here
foo: 1
};
db.things.find(query).sort(sort).limit(100).toArray(callback);
有谁知道我是否可以使用运营商来实现这一目标?
答案 0 :(得分:2)
你想要做的是"加权"要做到这一点,您需要使用.aggregate()
方法来提供对聚合管道的访问。管道中的第一个阶段是$match
阶段,您可以在其中过滤以仅允许匹配的文档未经修改地传递到下一个管道阶段。然后您需要使用$project
和$sort
管道运算符如图所示here
db.things.aggregate([
{ "$match": {
"$or": [
{ "_id": {
"$in": ['bbb', 'ddd'] }
},
{ "foo": { "$lt": 20000 } } ]
}},
{ "$project": {
"foo": 1,
"weight": {
"$cond": [
{ "$eq": [ "$_id", "bbb" ] },
10,
{ "$cond": [
{ "$eq": [ "$_id", "ddd" ] },
8,
0
]}
]
}
}},
{ "$sort": { "weight": -1 }}
])
哪个收益率:
{ "_id" : "bbb", "foo" : 32476, "weight" : 10 }
{ "_id" : "ddd", "foo" : 45253, "weight" : 8 }
{ "_id" : "eee", "foo" : 15545, "weight" : 0 }
由于$in
中不允许$cond
运算符,您可以使用$map
返回一个元素数组数组,然后使用$setIsSubset
运算符检查_id
运算符是否$map
1}}出现在你的第二个数组中。当然,因为"输入" db.things.aggregate([
{ "$match": {
"$or": [
{ _id: {
"$in": ['bbb', 'ddd'] }
},
{ foo: { $lt: 20000 } }
]
}},
{ "$project": {
"foo": 1,
"weight": {
"$cond": [
{ "$setIsSubset": [
{ "$map": {
"input": { "$literal": ["id"] },
"as": "id",
"in": "$_id"
}},
[ "bbb","ddd" ]
]},
4,
0
]
}
}},
{ "$sort": { "weight": -1 } }
])
必须是您需要使用$literal
表达式的数组。
{ "_id" : "bbb", "foo" : 32476, "weight" : 4 }
{ "_id" : "ddd", "foo" : 45253, "weight" : 4 }
{ "_id" : "eee", "foo" : 15545, "weight" : 0 }
返回:
com.google.android.gms:play-services-analytics
请注意,如果你有很多" _id"在你的阵列中。
答案 1 :(得分:0)
如果将聚合框架与$project
一起使用,则可以部分实现此目的。在下面的代码中,仅在_id
上匹配的记录首先出现,但是,如果满足两个过滤条件,则不适用。遗憾的是,您无法在$in
子句中使用$project
运算符。
var query = [{
$match: {
$or: [{
_id: {
$in: ['bbb', 'ddd']
}
}, {
foo: {
$lt: 20000
}
}]
}
}, {
$project: {
"_id": 1,
"foo": 1,
"sort_flag": {
"$or": [{
"$gte": ["$foo", 20000]
}]
}
}
}, {
$sort: {
"sort_flag": -1
}
}]
db.things.aggregate(query)