これはもちろん、「3」のすべてのフィールドが中に含まれていることを考えると、おそらくあなたが思うよりも多くの簡単です1 "country"
文書。つまり、$lookup
を"country_id"
で実行し、取得したコンテンツを使用して他のフィールドにデータを入力するだけです。配列は$lookup
によってでマッチングされた後
{
"_id" : 1,
"email" : "[email protected]",
"userId" : "AD",
"userName" : "admin",
"country" : {
"country_id" : 1,
"userId" : "AD",
"phone" : "0000000000",
"stateinfo": {
"state_id" : 1,
"state_name" : "State1"
},
"cityinfo": {
"city_id" : 1,
"city_name" : "city1"
}
}
だからそれがすべての最初の試合を取得するためにmatcingを行うためにを使用して$arrayElemAt
にダウンしています:のようにあなたに結果を与える必要があります
var pipeline = [
{ "$lookup": {
"from": "country",
"localField": "country",
"foreignField": "country_id",
"as": "country"
}},
{ "$project": {
"email": 1,
"userId": 1,
"userName": 1,
"country": {
"$arrayElemAt": [
{ "$filter": {
"input": {
"$map": {
"input": "$country",
"as": "country",
"in": {
"country_id": "$$country.country_id",
"userId": "$$country.userId",
"phone": "$$country.phone",
"stateInfo": {
"$arrayElemAt": [
{ "$filter": {
"input": "$$country.stateInfo",
"as": "state",
"cond": { "$eq": [ "$$state.state_id", "$state" ] }
}},
0
]
},
"cityinfo": {
"$arrayElemAt": [
{ "$filter": {
"input": "$$country.cityinfo",
"as": "city",
"cond": { "$eq": [ "$$city.city_id", "$city" ] }
}},
0
]
}
}
}
},
"as": "country",
"cond": { "$eq": [ "$$country.userId", "$userId" ] }
}},
0
]
}
}}
]
db.people.aggregate(pipeline)
フィルタリングされた各配列。
外側の配列には「内側」の配列があるため、「外側」のソースには$map
を使用し、それぞれの「内側」配列にはを適用します。
$let
を使用すると、「縮小」された配列の内容を返されたサブ文書に変換し、その結果のプロパティを参照するだけで、より平坦な応答を得ることができますが、配列要素は上記と同じままである。 PHPの構造変換に
:
$pipeline = array(
array(
'$lookup' => array(
'from' => 'country',
'localField' => 'country'
'foreignField' => 'country_id',
'as' => 'country'
)
)
array(
'$project' => array(
'email' => 1,
'userId' => 1,
'userName' => 1,
'country' => array(
'$arrayElemAt' => array(
array(
'$filter' => array(
'input' => array(
'$map' => array(
'input' => '$country',
'as' => 'country',
'in' => {
'country_id' => '$$country.country_id',
'userId' => '$$country.userId',
'phone' => '$$country.phone',
'stateInfo' => array(
'$arrayElemAt' => array(
array(
'$filter' => array(
'input' => '$$country.stateInfo',
'as' => 'state',
'cond' => array('$eq' => array('$$state.state_id', '$state'))
)
),
0
)
),
'cityinfo' => array(
'$arrayElemAt' => array(
array(
'$filter' => array(
'input' => '$$country.cityinfo',
'as' => 'city',
'cond' => array('$eq' => array('$$city.city_id', '$city'))
)
),
0
)
)
}
)
),
'as' => 'country',
'cond' => array('$eq' => array('$$country.userId', '$userId'))
)
),
0
)
)
)
)
);
$people->aggregate($pipeline);
あなたは通常、あなたがパイプライン構造をダンプすることでJSONの例から作業しているとき、あなたのPHPは、JSONの構造と一致して確認することができます。
echo json_encode($pipeline, JSON_PRETTY_PRINT)
そして、それあなたは間違って行くことはできません。
ここで別の最後の注意として、$lookup
の後のプロセスは、非常に効率的であっても非常に「複雑」です。だから、私は、この集約パイプラインをさらに活用し、実際に何かを集約する必要がなければ、サーバー上で行うのではなく、クライアントコードでその「フィルタリング」を行うほうがよいでしょう。
同じことをするクライアントコードは、集約パイプラインに行うために必要なものよりはるかに「鈍い」です。したがって、実際には、一致した配列を減らすことで帯域幅の使用量を大幅に節約できない場合や、代わりに別のクエリを実行してコードを実行したり、別のクエリを実行したりすることができます。
これらのコレクションは、PHPまたはmongoにありますか? – Chris
@chris – Suresh