ODMとしてMongoDBとMongooseを使用しており、同じステートメントでpopulate
とgroup by
を使用してクエリを作成しようとしています。
これが私の簡単なドキュメントモデルです。
var userSchema = new Schema({
username: String
});
var messageSchema = new Schema({
from: { type: Schema.ObjectId, ref: 'User' },
to: { type: Schema.ObjectId, ref: 'User' },
message: String,
date: { type: Date, default: Date.now }
});
私は、1人のユーザーのすべてのメッセージを取得しようとしています。ユーザーが会話するたびにグループ化します。私はこのようにしてみました:
this.find({ 'to': user })
.sort({ 'date': 1 })
.group('from')
.populate(['from', 'to'])
.exec(callback);
しかし、残念ながら、私のモデルにはgroup
メソッドがありません。これを機能させるための解決策はありますか?
ありがとうございました。
$ lookup populateを使用した例では、lookupが配列として生成されるため、$ unwindになります。
Message.aggregate(
[
{ "$match": { "to": user } },
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": "from",
"to": { "$first": "$to" },
"message": { "$first": "$message" },
"date": { "$first": "$date" },
"origId": { "$first": "$_id" }
}},
{ "$lookup": {
"from": "users",
"localField": "from",
"foreignField": "_id",
"as": "from"
}},
{ "$lookup": {
"from": "users",
"localField": "to",
"foreignField": "_id",
"as": "to"
}},
{ "$unwind": { "path" : "$from" } },
{ "$unwind": { "path" : "$to" } }
],
function(err,results) {
if (err) throw err;
return results;
}
)
ここで使用するより良いオプションは .aggregate()
です。これは、MongoDBの .group()
メソッドとは異なり、ネイティブコードの実装です。結果を処理するJavaScriptエンジン。
ただし、.populate()
のようなメソッドは直接サポートされていません。これは、集約パイプラインおよび他のメソッドが現在のモデルのスキーマに基づく応答を厳密に返さないため、仕様によるものです。あなたがしていることを「想定」するのは間違っているので、単なる生のオブジェクト応答です。
ただし、応答をマングース文書として「キャスト」し、必要なパスで .populate()
のモデル形式を呼び出すことを妨げるものはありません。
_Message.aggregate(
[
{ "$match": { "to": user } },
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": "from",
"to": { "$first": "$to" },
"message": { "$first": "$message" },
"date": { "$first": "$date" },
"origId": { "$first": "$_id" }
}}
],
function(err,results) {
if (err) throw err;
results = result.map(function(doc) {
doc.from = doc._id
doc._id = doc.origId;
delete doc.origId;
return new Message( doc )
});
User.populate( results, { "path": "from to" }, function(err,results) {
if (err) throw err;
console.log( JSON.stringify( results, undefined, 4 ) );
});
}
)
_
もちろん、それは実際には、演算子によって暗示されるように、各「from」から _$first
_ メッセージを返すだけです。 。
「group by」が本当に意味することは、実際には「ソート」です。
_Message.find({ "to": user })
.sort({ "from": 1, "date": 1 })
.populate("from to")
.exec(function(err,messsages) {
if (err) throw err;
console.log( JSON.stringify( messages, undefined, 4 ) );
});
_
コンテキストが「すべてのメッセージ」を示しており、.aggregate()
や.group()
コレクションメソッドなどのグループ化演算子によって暗示されるものではありません。したがって、メッセージは、特定のグループ化ではなく、ソートによって「グループ化」されます。
後者はあなたが本当に求めているもののように聞こえますが、実際に「グループ化」を意図している場合は、.populate()
を使用する方法とともに集約の例があります。