배열의 ObjectId에 대한 $ lookup
단일 ObjectId가 아닌 ObjectId의 배열 인 필드에서 $ lookup을 수행하는 구문은 무엇입니까?
주문 문서 예 :
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
]
}
작동하지 않는 쿼리 :
db.orders.aggregate([
{
$lookup:
{
from: "products",
localField: "products",
foreignField: "_id",
as: "productObjects"
}
}
])
원하는 결과
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
],
productObjects: [
{<Car Object>},
{<Bike Object>}
],
}
$lookup
집계 파이프 라인 단계는 배열을 직접 작동하지 않습니다. 디자인의 주요 의도는 가능한 관련 데이터에 대한 "일대 다"유형의 조인 (또는 실제로 "조회") 인 "왼쪽 조인"입니다. 그러나 값은 배열이 아닌 단수를위한 것입니다.
따라서이 $lookup
작업 을 수행하려면 작업 을 수행하기 전에 먼저 내용을 "비정규 화"해야합니다 . 그리고 그것은 다음을 사용하는 것을 의미합니다 $unwind
.
db.orders.aggregate([
// Unwind the source
{ "$unwind": "$products" },
// Do the lookup matching
{ "$lookup": {
"from": "products",
"localField": "products",
"foreignField": "_id",
"as": "productObjects"
}},
// Unwind the result arrays ( likely one or none )
{ "$unwind": "$productObjects" },
// Group back to arrays
{ "$group": {
"_id": "$_id",
"products": { "$push": "$products" },
"productObjects": { "$push": "$productObjects" }
}}
])
후 $lookup
일치 각 배열 구성원 결과가 있으므로, 배열 자체가 $unwind
다시 $group
에 $push
최종 결과에 대한 새로운 배열.
찾을 수없는 "왼쪽 조인"일치 항목은 지정된 제품의 "productObjects"에 대한 빈 배열을 생성하므로 두 번째 $unwind
가 호출 될 때 "제품"요소에 대한 문서가 무효화됩니다 .
배열에 직접 적용하는 것이 좋지만 단일 값을 가능한 많은 수에 일치시켜 현재 작동하는 방식입니다.
As $lookup
is basically very new, it currently works as would be familiar to those who are familiar with mongoose as a "poor mans version" of the .populate()
method offered there. The difference being that $lookup
offers "server side" processing of the "join" as opposed to on the client and that some of the "maturity" in $lookup
is currently lacking from what .populate()
offers ( such as interpolating the lookup directly on an array ).
This is actually an assigned issue for improvement SERVER-22881, so with some luck this would hit the next release or one soon after.
디자인 원칙에 따라 현재 구조는 좋거나 나쁘지 않지만 "조인"을 만들 때 오버 헤드가 발생합니다. 따라서 처음에는 MongoDB의 기본 원칙이 적용됩니다. 여기서 하나의 컬렉션에 "사전 조인 된"데이터로 "살 수있는"경우 그렇게하는 것이 가장 좋습니다.
$lookup
일반적인 원칙 으로 말할 수있는 다른 한 가지는 여기에서 "조인"의 의도가 여기에 표시된 것과 다른 방식으로 작동하는 것입니다. 따라서 "상위"문서 내에서 다른 문서의 "관련 ID"를 유지하는 대신 "관련 문서"에 "상위"에 대한 참조가 포함되어있는 경우 가장 잘 작동하는 일반적인 원칙이 있습니다.
따라서 $lookup
몽구스와 같은 .populate()
것이 클라이언트 측 조인을 수행 하는 방식의 반대 인 "관계 설계"로 "가장 잘 작동"한다고 할 수 있습니다 . 대신 각 "다"내에서 "하나"를 식별하면 $unwind
먼저 배열 을 사용할 필요없이 관련 항목을 가져옵니다.
$lookup
집계 파이프 라인 단계는 NOW (3.3.4 버전) 배열과 직접 작동합니다.
참조 : 로컬 (다중) 값 배열과 외래 (단일) 값 간 조회
pipeline
스테이지를 사용하여 하위 문서 배열에 대한 검사를 수행 할 수도 있습니다.
다음은 python
(죄송합니다 나는 뱀 사람입니다) 를 사용한 예 입니다.
db.products.aggregate([
{ '$lookup': {
'from': 'products',
'let': { 'pid': '$products' },
'pipeline': [
{ '$match': { '$expr': { '$in': ['$_id', '$$pid'] } } }
// Add additional stages here
],
'as':'productObjects'
}
])
The catch here is to match all objects in the ObjectId
array
(foreign _id
that is in local
field/prop products
).
You can also clean up or project the foreign records with additional stage
s, as indicated by the comment above.
use $unwind you will get the first object instead of array of objects
query:
db.getCollection('vehicles').aggregate([
{
$match: {
status: "AVAILABLE",
vehicleTypeId: {
$in: Array.from(newSet(d.vehicleTypeIds))
}
}
},
{
$lookup: {
from: "servicelocations",
localField: "locationId",
foreignField: "serviceLocationId",
as: "locations"
}
},
{
$unwind: "$locations"
}
]);
result:
{
"_id" : ObjectId("59c3983a647101ec58ddcf90"),
"vehicleId" : "45680",
"regionId" : 1.0,
"vehicleTypeId" : "10TONBOX",
"locationId" : "100",
"description" : "Isuzu/2003-10 Ton/Box",
"deviceId" : "",
"earliestStart" : 36000.0,
"latestArrival" : 54000.0,
"status" : "AVAILABLE",
"accountId" : 1.0,
"locations" : {
"_id" : ObjectId("59c3afeab7799c90ebb3291f"),
"serviceLocationId" : "100",
"regionId" : 1.0,
"zoneId" : "DXBZONE1",
"description" : "Masafi Park Al Quoz",
"locationPriority" : 1.0,
"accountTypeId" : 0.0,
"locationType" : "DEPOT",
"location" : {
"makani" : "",
"lat" : 25.123091,
"lng" : 55.21082
},
"deliveryDays" : "MTWRFSU",
"timeWindow" : {
"timeWindowTypeId" : "1"
},
"address1" : "",
"address2" : "",
"phone" : "",
"city" : "",
"county" : "",
"state" : "",
"country" : "",
"zipcode" : "",
"imageUrl" : "",
"contact" : {
"name" : "",
"email" : ""
},
"status" : "",
"createdBy" : "",
"updatedBy" : "",
"updateDate" : "",
"accountId" : 1.0,
"serviceTimeTypeId" : "1"
}
}
{
"_id" : ObjectId("59c3983a647101ec58ddcf91"),
"vehicleId" : "81765",
"regionId" : 1.0,
"vehicleTypeId" : "10TONBOX",
"locationId" : "100",
"description" : "Hino/2004-10 Ton/Box",
"deviceId" : "",
"earliestStart" : 36000.0,
"latestArrival" : 54000.0,
"status" : "AVAILABLE",
"accountId" : 1.0,
"locations" : {
"_id" : ObjectId("59c3afeab7799c90ebb3291f"),
"serviceLocationId" : "100",
"regionId" : 1.0,
"zoneId" : "DXBZONE1",
"description" : "Masafi Park Al Quoz",
"locationPriority" : 1.0,
"accountTypeId" : 0.0,
"locationType" : "DEPOT",
"location" : {
"makani" : "",
"lat" : 25.123091,
"lng" : 55.21082
},
"deliveryDays" : "MTWRFSU",
"timeWindow" : {
"timeWindowTypeId" : "1"
},
"address1" : "",
"address2" : "",
"phone" : "",
"city" : "",
"county" : "",
"state" : "",
"country" : "",
"zipcode" : "",
"imageUrl" : "",
"contact" : {
"name" : "",
"email" : ""
},
"status" : "",
"createdBy" : "",
"updatedBy" : "",
"updateDate" : "",
"accountId" : 1.0,
"serviceTimeTypeId" : "1"
}
}
Aggregating with $lookup
and subsequent $group
is pretty cumbersome, so if (and that's a medium if) you're using node & Mongoose or a supporting library with some hints in the schema, you could use a .populate()
to fetch those documents:
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
var productSchema = Schema({ ... });
var orderSchema = Schema({
_id : Number,
products: [ { type: Schema.Types.ObjectId, ref: "Product" } ]
});
var Product = mongoose.model("Product", productSchema);
var Order = mongoose.model("Order", orderSchema);
...
Order
.find(...)
.populate("products")
...
참고URL : https://stackoverflow.com/questions/34967482/lookup-on-objectids-in-an-array
'program tip' 카테고리의 다른 글
자바에서 goto 문에 대한 대안 (0) | 2020.09.21 |
---|---|
Angular.js 여러 요소에서 ng-repeat (0) | 2020.09.21 |
Python에서 콘솔 출력 교체 (0) | 2020.09.21 |
SQLAlchemy-테이블 목록 가져 오기 (0) | 2020.09.21 |
Bootstrap을 사용하여 모바일에 테이블을 표시하는 방법은 무엇입니까? (0) | 2020.09.21 |