dmr*_*r07 5 mongoose mongodb node.js mongodb-query aggregation-framework
我有 3 个数组,ObjectIds
我想连接成一个数组,然后按创建日期排序。$setUnion正是我想要的,但我想尝试不使用它。
我想要排序的对象的架构:
var chirpSchema = new mongoose.Schema({
interactions: {
_liked : ["55035390d3e910505be02ce2"] // [{ type: $oid, ref: "interaction" }]
, _shared : ["507f191e810c19729de860ea", "507f191e810c19729de860ea"] // [{ type: $oid, ref: "interaction" }]
, _viewed : ["507f1f77bcf86cd799439011"] // [{ type: $oid, ref: "interaction" }]
}
});
Run Code Online (Sandbox Code Playgroud)
期望的结果:将 _liked、_shared 和 _viewed 连接到一个数组中,然后使用aggregate
管道按创建日期对它们进行排序。见下文
["507f1f77bcf86cd799439011", "507f191e810c19729de860ea", "507f191e810c19729de860ea", "55035390d3e910505be02ce2"]
Run Code Online (Sandbox Code Playgroud)
我知道我应该使用$push
、$each
、$group
、 和$unwind
以某种组合或其他方式,但我在拼凑文档以实现这一点时遇到困难。
更新:查询
model_user.aggregate([
{ $match : { '_id' : { $in : following } } }
, { $project : { 'interactions' : 1 } }
, { $project : {
"combined": { $setUnion : [
"$interactions._liked"
, "$interactions._shared"
, "$interactions._viewed"
]}
}}
])
.exec(function (err, data) {
if (err) return next(err);
next(data); // Combined is returning null
})
Run Code Online (Sandbox Code Playgroud)
如果所有对象_id
值都是“唯一的”,那么这$setUnion
是您的最佳选择。当然,它不以任何方式“排序”,因为它与“集合”一起使用,并且不能保证顺序。但您始终可以放松并进行排序。
[
{ "$project": {
"combined": { "$setUnion": [
{ "$ifNull": [ "$interactions._liked", [] ] },
{ "$ifNull": [ "$interactions._shared", [] ] },
{ "$ifNull", [ "$interactions._viewed", [] ] }
]}
}},
{ "$unwind": "$combined" },
{ "$sort": { "combined": 1 } },
{ "$group": {
"_id": "$_id",
"combined": { "$push": "$combined" }
}}
]
Run Code Online (Sandbox Code Playgroud)
当然,由于这是一组不同值,因此在处理每个数组$addToSet
后,您可以使用旧方法来代替 , :$unwind
[
{ "$unwind": "$interactions._liked" },
{ "$unwind": "$interactions._shared" },
{ "$unwind": "$interactions._viewed" },
{ "$project": {
"interactions": 1,
"type": { "$const": [ "liked", "shared", "viewed" ] }
}}
{ "$unwind": "$type" },
{ "$group": {
"_id": "$_id",
"combined": {
"$addToSet": {
"$cond": [
{ "$eq": [ "$type", "liked" ] },
"$interactions._liked",
{ "$cond": [
{ "$eq": [ "$type", "shared" ] },
"$interactions._shared",
"$interactions._viewed"
]}
]
}
}
}},
{ "$unwind": "$combined" },
{ "$sort": { "combined": 1 } },
{ "$group": {
"_id": "$_id",
"combined": { "$push": "$combined" }
}}
]
Run Code Online (Sandbox Code Playgroud)
但同样的事情仍然适用于订购。
未来的版本甚至能够连接数组而不减少为“集合”:
[
{ "$project": {
"combined": { "$concatArrays": [
"$interactions._liked",
"$interactions._shared",
"$interactions._viewed"
]}
}},
{ "$unwind": "$combined" },
{ "$sort": { "combined": 1 } },
{ "$group": {
"_id": "$_id",
"combined": { "$push": "$combined" }
}}
]
Run Code Online (Sandbox Code Playgroud)
但仍然无法在不处理$unwind
和的情况下对结果重新排序$sort
。
因此,您可能会认为,除非您需要跨多个文档进行分组,否则基本的“连接和排序”操作最好在客户端代码中处理。目前,MongoDB 无法在数组上“就地”执行此操作,因此客户端代码中的每个文档是您最好的选择。
但是,如果您确实需要对多个文档进行分组,那么此处所示的方法适合您。
另请注意,此处的“创建”是指创建 ObjectId 值本身,而不是引用对象的其他属性。如果您需要这些,那么您可以在聚合或查询之后对 id 值执行填充,当然还可以在客户端代码中进行排序。
归档时间: |
|
查看次数: |
2042 次 |
最近记录: |