DBef로 $lookup하는 Mongo 방법
문제가 생겼어요.컬렉션 A가 다음과 같다고 가정합니다.
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"bid" : [
DBRef("B", ObjectId("582abcd85d2dfa67f44127e0")),
DBRef("B", ObjectId("582abcd85d2dfa67f44127e1"))
]
}
및 컬렉션 B:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e0"),
"status" : NumberInt(1),
"seq" : NumberInt(0)
},
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"status" : NumberInt(1),
"seq" : NumberInt(0)
}
나는 '입찰'을 어떻게 조회하는지 모릅니다.나는 노력했다.
db.A.aggregate(
[
{$unwind: {path: "$bid"}},
{$lookup: {from: "B", localField: "bid", foreignField: "_id", as: "bs"}},
]
)
그리고.
db.A.aggregate(
[
{$unwind: {path: "$bid"}},
{$lookup: {from: "B", localField: "bid.$id", foreignField: "_id", as: "bs"}},
]
)
하지만 효과가 없습니다.도와줄 사람?감사해요.
사실 다른 답은 틀렸습니다.애그리게이터 내에서 DBref 필드를 조회할 수 있으며, 맵 축소가 필요하지 않습니다.
해결책
db.A.aggregate([
{
$project: {
B_fk: {
$map: {
input: {
$map: {
input:"$bid",
in: {
$arrayElemAt: [{$objectToArray: "$$this"}, 1]
},
}
},
in: "$$this.v"}},
}
},
{
$lookup: {
from:"B",
localField:"B_fk",
foreignField:"_id",
as:"B"
}
}
])
결과
{
"_id" : ObjectId("59bb79df1e9c00162566f581"),
"B_fk" : null,
"B" : [ ]
},
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"B_fk" : [
ObjectId("582abcd85d2dfa67f44127e0"),
ObjectId("582abcd85d2dfa67f44127e1")
],
"B" : [
{
"_id" : ObjectId("582abcd85d2dfa67f44127e0"),
"status" : NumberInt("1"),
"seq" : NumberInt("0")
}
]
}
짧은 설명
$map을 사용하여 DBref를 반복하고 각 DBref를 배열로 분할한 다음 $id 필드만 유지한 다음 $$this.v를 사용하여 k:v 형식을 제거하고 ObjectId만 유지하고 나머지는 모두 제거합니다.이제 ObjectId를 조회할 수 있습니다.
단계별 설명
애그리게이터 내에서 DBRef BSON 유형은 두 개 또는 세 개의 필드(ref, id 및 db)로 객체처럼 처리할 수 있습니다.
수행하는 경우:
db.A.aggregate([
{
$project: {
First_DBref_as_array: {$objectToArray:{$arrayElemAt:["$bid",0]}},
Second_DBref_as_array: {$objectToArray:{$arrayElemAt:["$bid",1]}},
}
},
])
결과는 다음과 같습니다.
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"First_DBref_as_array : [
{
"k" : "$ref",
"v" : "B"
},
{
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
}
],
"Second_DBref_as_array" : [
{
"k" : "$ref",
"v" : "B"
},
{
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
}
]
}
dbref를 배열로 변환한 후에는 다음과 같이 인덱스 1의 값만 쿼리하여 쓸모없는 필드를 제거할 수 있습니다.
db.A.aggregate([
{
$project: {
First_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
Second_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
}
},
])
결과:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"First_DBref_as_array" : {
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
},
"Second_DBref_as_array" : {
"k" : "$id",
"v" : ObjectId("582abcd85d2dfa67f44127e0")
}
}
그런 다음 "$myvalue"를 가리키면 마침내 원하는 값에 도달할 수 있습니다.v", 이와 같이
db.A.aggregate([
{
$project: {
first_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
second_DBref_as_array: {$arrayElemAt: [{$objectToArray:{$arrayElemAt:["$bid",0]}},1]},
}
},
{
$project: {
first_DBref_as_ObjectId: "$first_DBref_as_array.v",
second_DBref_as_ObjectId: "$second_DBref_as_array.v"
}
}
])
결과:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"first_DBref_as_ObjectId" : ObjectId("582abcd85d2dfa67f44127e0"),
"second_DBref_as_ObjectId" : ObjectId("582abcd85d2dfa67f44127e0")
}
일반적인 파이프라인에서는 이러한 중복 단계가 모두 필요하지 않으며, 중첩된 $map을 사용하면 한 번에 동일한 결과를 얻을 수 있습니다.
db.A.aggregate([
{
$project: {
B_fk: { $map : {input: { $map: { input:"$bid",
in: { $arrayElemAt: [{$objectToArray: "$$this"}, 1 ]}, } },
in: "$$this.v"}},
}
},
])
결과:
{
"_id" : ObjectId("582abcd85d2dfa67f44127e1"),
"B_fk" : [
ObjectId("582abcd85d2dfa67f44127e0"),
ObjectId("582abcd85d2dfa67f44127e1")
]
}
자유롭게 묻지는 않더라도 충분히 설명이 명확했으면 좋겠습니다.
mongoDB 3.4 이후로는 이것이 불가능합니다.$match 단계를 제외하고 집계 파이프라인에서 DBRef를 사용할 수 없습니다.
DBef를 없애고 수동 참조로 전환하는 것이 좋습니다.하지만 DBEf를 유지해야 하는 경우 다음과 같은 (못된) 해결책이 있습니다.
먼저 "C"라는 이름의 새 컬렉션을 생성합니다. 여기서 mapReduce:
db.A.mapReduce(
function() {
var key = this._id;
var value = [];
for ( var index = 0; index < this.bid.length; index++){
value.push(this.bid[index].$id);
}
emit(key, value);
},
function(key,values) {
return values;
},
{
"query": {},
"out": "C"
}
)
그런 다음 새 "C" 컬렉션에 대해 집계 쿼리를 실행합니다.
db.C.aggregate([
{
$unwind:"$value"
},
{
$lookup:{
from:"B",
localField:"value",
foreignField:"_id",
as:"bs"
}
}
]);
출력:
{
"_id":ObjectId("582abcd85d2dfa67f44127e1"),
"value":ObjectId("582abcd85d2dfa67f44127e0"),
"bs":[
{
"_id":ObjectId("582abcd85d2dfa67f44127e0"),
"status":1,
"seq":0
}
]
}{
"_id":ObjectId("582abcd85d2dfa67f44127e1"),
"value":ObjectId("582abcd85d2dfa67f44127e1"),
"bs":[
{
"_id":ObjectId("582abcd85d2dfa67f44127e1"),
"status":1,
"seq":0
}
]
}
2021년에 누군가가 이곳에 올 경우를 대비해서:
MongoDB 4.3.3부터는 OP의 두 번째 쿼리가 작동합니다.
db.A.aggregate(
[
{$unwind: {path: "$bid"}},
{$lookup: {from: "B", localField: "bid.$id", foreignField: "_id", as: "bs"}},
]
)
결과는 다음과 같습니다.
{
"_id":ObjectId("582abcd85d2dfa67f44127e1"),
"bid":DBRef("B", "ObjectId("582abcd85d2dfa67f44127e0")),
"bs":[
{
"_id":ObjectId("582abcd85d2dfa67f44127e0")",
"status":1,
"seq":0
}
]
}{
"_id":ObjectId("582abcd85d2dfa67f44127e1"),
"bid":DBRef("B", "ObjectId("582abcd85d2dfa67f44127e1")),
"bs":[
{
"_id":ObjectId("582abcd85d2dfa67f44127e1"),
"status":1,
"seq":0
}
]
}
자세한 내용은 SERVER-14466을 참조하십시오.
언급URL : https://stackoverflow.com/questions/40622714/mongo-how-to-lookup-with-dbref
'programing' 카테고리의 다른 글
딕트와 같은 역할을 하는 파이썬 클래스 (0) | 2023.07.16 |
---|---|
오리진이 0에서 시작하도록 강제 적용 (0) | 2023.07.16 |
SQL Server 2008 DateTimeOffset을 DateTime으로 변환하는 방법 (0) | 2023.07.16 |
값을 전환하는 방법? (0) | 2023.07.16 |
Firebase용 Cloud Functions(multer, busboy)에서 Express를 사용하여 HTTP 파일 업로드를 수행하는 방법 (0) | 2023.07.06 |