Mongodb 聚合查找 return 仅数组的一个字段
Mongodb aggregate lookup return only one field of array
我有一些 collection 用于我们的项目。
- 演员阵容collection 包含电影演员阵容
- 内容collection包含电影内容
我想 运行 聚合查找以获取有关具有位置类型的电影演员表的信息。
我删除了 collections 不必要的详细信息字段。
演员详情:
{
"_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)
}
当我 运行 使用波纹管查询聚合查找时,在新生成的查找数组中只有一个转换内容如果按照上面的转换数组值聚合查找应该 return 两种类型的两个转换内容。在 casts 数组值中存在两种类型的演员表,1) 作家和导演。但 returned 导演投射内容。 _casts 应该包含两个 object 而不是一个 object!
聚合查找查询:
{$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
终于我的问题解决了。这个查询只有一个问题,这个查询不显示根文档字段。终于解决了这个问题。最终查询存在于 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"}}},
])
EDIT-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()
您的演员表 collection 仅显示 1 个文档。同样,您的目录 collection 仅显示 1 个文档。
这是 1 对 1,而不是 1 对 2。聚合按设计工作。
目录文档有 2 个 "casts." 这 2 个转换是 sub-documents。与 sub-documents 或 re-design 您的 collection 一起工作。我不喜欢使用 sub-documents 除非我知道我不需要将它们用作 look-ups 或加入它们。
我会建议你 re-design 你的 collection。
您的内容 collection(这让我想起了 "Movies")可能如下所示:
_id
title
releaseDate
genre
etc.
您可以像这样创建 MovieCasts collection:
_id
movieId (this is _id from Contents collection, above)
castId (this is _id from Casts collection, below)
施法
_id
name
age
etc.
这是预期的行为。
来自docs
,
If your localField is an array, you may want to add an $unwind stage
to your pipeline. Otherwise, the equality condition between the
localField and foreignField is foreignField: { $in: [
localField.elem1, localField.elem2, ... ] }.
因此,要将每个本地字段数组元素与外部字段元素连接起来,您必须 $unwind
本地数组。
db.content.aggregate([
{"$unwind":"$casts"},
{"$lookup":{"from":"casts","localField":"casts._id","foreignField":"_id","as":"_casts"}}
])
Vendor Collection
Items Collection
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
}
}
]);
Output
我有一些 collection 用于我们的项目。
- 演员阵容collection 包含电影演员阵容
- 内容collection包含电影内容
我想 运行 聚合查找以获取有关具有位置类型的电影演员表的信息。
我删除了 collections 不必要的详细信息字段。
演员详情:
{
"_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)
}
当我 运行 使用波纹管查询聚合查找时,在新生成的查找数组中只有一个转换内容如果按照上面的转换数组值聚合查找应该 return 两种类型的两个转换内容。在 casts 数组值中存在两种类型的演员表,1) 作家和导演。但 returned 导演投射内容。 _casts 应该包含两个 object 而不是一个 object!
聚合查找查询:
{$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 终于我的问题解决了。这个查询只有一个问题,这个查询不显示根文档字段。终于解决了这个问题。最终查询存在于 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"}}},
])
EDIT-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()
您的演员表 collection 仅显示 1 个文档。同样,您的目录 collection 仅显示 1 个文档。
这是 1 对 1,而不是 1 对 2。聚合按设计工作。
目录文档有 2 个 "casts." 这 2 个转换是 sub-documents。与 sub-documents 或 re-design 您的 collection 一起工作。我不喜欢使用 sub-documents 除非我知道我不需要将它们用作 look-ups 或加入它们。
我会建议你 re-design 你的 collection。
您的内容 collection(这让我想起了 "Movies")可能如下所示:
_id
title
releaseDate
genre
etc.
您可以像这样创建 MovieCasts collection:
_id
movieId (this is _id from Contents collection, above)
castId (this is _id from Casts collection, below)
施法
_id
name
age
etc.
这是预期的行为。
来自docs
,
If your localField is an array, you may want to add an $unwind stage to your pipeline. Otherwise, the equality condition between the localField and foreignField is foreignField: { $in: [ localField.elem1, localField.elem2, ... ] }.
因此,要将每个本地字段数组元素与外部字段元素连接起来,您必须 $unwind
本地数组。
db.content.aggregate([
{"$unwind":"$casts"},
{"$lookup":{"from":"casts","localField":"casts._id","foreignField":"_id","as":"_casts"}}
])
Vendor Collection
Items Collection
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
}
}
]);
Output