node.js - MongoDB: Concatenate Multiple Arrays -
i have 3 arrays of objectids
want concatenate single array, , sort creation date. $setunion precisely want, i'd try without using it.
schema of object want sort:
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" }] } });
desired result: concatenate _liked, _shared, , _viewed single array, , sort them creation date using aggregate
pipeline. see below
["507f1f77bcf86cd799439011", "507f191e810c19729de860ea", "507f191e810c19729de860ea", "55035390d3e910505be02ce2"]
i know i'm suppose use $push
, $each
, $group
, , $unwind
in combination or other, i'm having trouble piecing documenation make happen.
update: query
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 returning null })
if object _id
values "unique" $setunion
best option. of course not "ordered" in way works "set", , not guarantee order. can unwind , $sort.
[ { "$project": { "combined": { "$setunion": [ { "$ifnull": [ "$interactions._liked", [] ] }, { "$ifnull": [ "$interactions._shared", [] ] }, { "$ifnull", [ "$interactions._viewed", [] ] } ]} }}, { "$unwind": "$combined" }, { "$sort": { "combined": 1 } }, { "$group": { "_id": "$_id", "combined": { "$push": "$combined" } }} ]
of course again since "set" of distinct values can old way instead $addtoset
, after processing $unwind
on each array:
[ { "$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" } }} ]
but still same thing applies ordering.
future releases have ability concatenate arrays without reducing "set":
[ { "$project": { "combined": { "$concatarrays": [ "$interactions._liked", "$interactions._shared", "$interactions._viewed" ]} }}, { "$unwind": "$combined" }, { "$sort": { "combined": 1 } }, { "$group": { "_id": "$_id", "combined": { "$push": "$combined" } }} ]
but still there no way re-order results without procesing $unwind
, $sort
.
you might therefore consider unless need grouped across multiple documents, basic "contenate , sort" operation best handled in client code. mongodb has no way "in place" on array @ present, per document in client code best bet.
but if need grouping on multiple documents, sort of approaches shown here you.
also note "creation" here means creation of objectid value , not other properties referenced objects. if need those, perform populate on id values after aggregation or query instead, , of course sort in client code.
Comments
Post a Comment