私たちのプロジェクトのためにいくつかのコレクションがあります。
位置タイプの映画キャストに関する情報を取得するために集計ルックアップを実行したいと思います。
コレクションの詳細の不要なフィールドを削除しました。
キャストの詳細:
{
"_id" : ObjectId("5a6cf47415621604942386cd"),
"fa_name" : "",
"en_name" : "Ehsan",
"fa_bio" : "",
"en_bio" : ""
}
コンテンツの詳細:
{
"_id" : ObjectId("5a6b8b734f1408137f79e2cc"),
"casts" : [
{
"_id" : ObjectId("5a6cf47415621604942386cd"),
"fa_fictionName" : "",
"en_fictionName" : "Ehsan2",
"positionType" : {
"id" : 3,
"fa_name" : "",
"en_name" : "Director"
}
},
{
"_id" : ObjectId("5a6cf47415621604942386cd"),
"fa_fictionName" : "",
"en_fictionName" : "Ehsan1",
"positionType" : {
"id" : 3,
"fa_name" : "",
"en_name" : "Writers"
}
}
],
"status" : 0,
"created" : Timestamp(1516997542, 4),
"updated" : Timestamp(1516997542, 5)
}
以下のクエリで集計ルックアップを実行すると、新しく生成されたルックアップ配列では、1つのキャストコンテンツのみがキャストされます。上記のキャスト配列値に従って、集計ルックアップは2つのタイプの2つのキャストコンテンツを返す必要があります。キャストの配列値には、1)ライターとディレクターの2種類のキャストが存在します。しかし、戻ってきた監督はコンテンツをキャストします。 _castsには、1つのオブジェクトではなく2つのオブジェクトが含まれている必要があります。
集計ルックアップクエリ:
{$lookup:{from:"casts",localField:"casts._id",foreignField:"_id",as:"_casts"}}
結果:
{
"_id" : ObjectId("5a6b8b734f1408137f79e2cc"),
"casts" : [
{
"_id" : ObjectId("5a6cf47415621604942386cd"),
"fa_fictionName" : "",
"en_fictionName" : "Ehsan2",
"positionType" : {
"id" : 3,
"fa_name" : "",
"en_name" : "Director"
}
},
{
"_id" : ObjectId("5a6cf47415621604942386cd"),
"fa_fictionName" : "",
"en_fictionName" : "Ehsan1",
"positionType" : {
"id" : 3,
"fa_name" : "",
"en_name" : "Writers"
}
}
],
"_casts" : [
{
"_id" : ObjectId("5a6cf47415621604942386cd"),
"fa_name" : "",
"en_name" : "Ehsan",
"fa_bio" : "",
"en_bio" : ""
}
],
"status" : 0,
"created" : Timestamp(1516997542, 4),
"updated" : Timestamp(1516997542, 5)
}
EDIT-1ついに私の問題は解決しました。このクエリの問題は1つだけです。このクエリでは、ルートドキュメントフィールドが表示されません。最終的にこの問題を解決します。最後に、クエリはEDIT-2に存在します。
クエリ:
db.contents.aggregate([
{"$unwind":"$casts"},
{"$lookup":{"from":"casts","localField":"casts._id","foreignField":"_id","as":"casts.info"}},
{"$unwind":"$casts.info"},
{"$group":{"_id":"$_id", "casts":{"$Push":"$casts"}}},
])
編集-2
db.contents.aggregate([
{"$unwind":"$casts"},
{"$lookup":{"from":"casts","localField":"casts._id","foreignField":"_id","as":"casts.info"}},
{"$unwind":"$casts.info"},
{$group:{"_id":"$_id", "data":{"$first":"$$ROOT"}, "casts":{"$Push":"$casts"}}},
{$replaceRoot:{"newRoot":{"$mergeObjects":["$data",{"casts":"$casts"}]}}},
{$project:{"casts":0}}
]).pretty()
これは予想される動作です。
docs
から、
LocalFieldが配列の場合は、パイプラインに$ unwindステージを追加することをお勧めします。それ以外の場合、localFieldとforeignFieldの間の等価条件はforeignField:{$ in:[localField.elem1、localField.elem2、...]}です。
したがって、各ローカルフィールド配列要素を外部フィールド要素と結合するには、 $unwind
ローカル配列。
db.content.aggregate([
{"$unwind":"$casts"},
{"$lookup":{"from":"casts","localField":"casts._id","foreignField":"_id","as":"_casts"}}
])
Castsコレクションには1つのドキュメントしか表示されません。同様に、コンテンツコレクションには1つのドキュメントしか表示されません。
これは1対1であり、1対2ではありません。Aggregateは設計どおりに機能しています。
コンテンツドキュメントには2つの「キャスト」があります。これらの2つのキャストはサブドキュメントです。それらをサブドキュメントとして使用するか、コレクションを再設計します。サブドキュメントをルックアップとして使用したり、サブドキュメントに参加したりする必要がないことがわかっている場合を除いて、サブドキュメントを使用するのは好きではありません。
コレクションを再設計することをお勧めします。
あなたのコンテンツコレクション(「映画」のことを考えさせられます)は次のようになります。
_id
title
releaseDate
genre
etc.
次のようにMovieCastsコレクションを作成できます。
_id
movieId (this is _id from Contents collection, above)
castId (this is _id from Casts collection, below)
キャスト
_id
name
age
etc.
db.items.aggregate([
{ $match:
{"item_id":{$eq:"I001"}}
},
{
$lookup:{
from:"vendor",
localField:"vendor_id",
foreignField:"vendor_id",
as:"vendor_details"
}
},
{
$unwind:"$vendor_details"
},
{
$project:{
"_id":0,
"vendor_id":0,
"vendor_details.vendor_company_description":0,
"vendor_details._id":0,
"vendor_details.country":0,
"vendor_details.city":0,
"vendor_details.website":0
}
}
]);