如何在 mongoDB 中使用多结果聚合/查找?
How to use aggregation/ lookup in mongoDB with multi results?
我下面有一个“图片”集合(注意:labels字段是一个数组,因为1张图片可能有很多标签)
{
"_id" : ObjectId("624d182b6a4e7f001ed5cd9f"),
"is_deleted" : false,
"labels" : [
{
"_id" : ObjectId("627a0fbc12458800209dd69c"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.440625,
"xmax" : 0.2953125,
"ymin" : 0.102083333333333,
"ymax" : 0.366666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69d"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.2546875,
"xmax" : 0.45,
"ymin" : 0.220833333333333,
"ymax" : 0.439583333333333
},
{
"_id" : ObjectId("627a0fbc12458800209dd69e"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.240625,
"xmax" : 0.48125,
"ymin" : 0.208333333333333,
"ymax" : 0.466666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69f"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.275618374558304,
"xmax" : 0.436395759717314,
"ymin" : 0.136470588235294,
"ymax" : 0.404705882352941
}
],
"img_name" : "6917328478506479617.jpg",
"img_originalname" : "frame27406302021-085850.jpg",
"img_desc" : "Cyber Sercurity multi upload",
"img_uri" : "http://localhost:8080/resources/images/2022/4/6/6917328478506479617.jpg",
"img_path" : "/resources/images/2022/4/6/6917328478506479617.jpg",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:33:47.120Z"),
"updatedAt" : ISODate("2022-05-10T07:09:48.306Z"),
"__v" : 0
}
下面是“标签”集合:
{
"_id" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"is_deleted" : false,
"labelName" : "Đông",
"description" : "qw",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:19:35.985Z"),
"updatedAt" : ISODate("2022-04-06T04:19:35.985Z"),
"__v" : 0,
"datanoiseId" : ObjectId("6261318b23a7a590480f92e6")
}
现在我想查找将有关标签的所有信息加入到图像中,所以我这样做了:
db.Image.aggregate([
{
$match: {
$and: [{"datasetId": ObjectId("624d14216a4e7f001ed5c459"), "is_deleted": false}]
}
},
{
$lookup: {
from: "Label",
localField: "labels.labelId",
foreignField: "_id",
as: "labelDocuments",
},
},
{ $sort : { "_id" : -1 } }
])
执行上述查询后得到的结果如下:
{
"_id" : ObjectId("624d182b6a4e7f001ed5cd9f"),
"is_deleted" : false,
"labels" : [
{
"_id" : ObjectId("627a0fbc12458800209dd69c"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.440625,
"xmax" : 0.2953125,
"ymin" : 0.102083333333333,
"ymax" : 0.366666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69d"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.2546875,
"xmax" : 0.45,
"ymin" : 0.220833333333333,
"ymax" : 0.439583333333333
},
{
"_id" : ObjectId("627a0fbc12458800209dd69e"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.240625,
"xmax" : 0.48125,
"ymin" : 0.208333333333333,
"ymax" : 0.466666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69f"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.275618374558304,
"xmax" : 0.436395759717314,
"ymin" : 0.136470588235294,
"ymax" : 0.404705882352941
}
],
"img_name" : "6917328478506479617.jpg",
"img_originalname" : "frame27406302021-085850.jpg",
"img_desc" : "Cyber Sercurity multi upload",
"img_uri" : "http://localhost:8080/resources/images/2022/4/6/6917328478506479617.jpg",
"img_path" : "/resources/images/2022/4/6/6917328478506479617.jpg",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:33:47.120Z"),
"updatedAt" : ISODate("2022-05-10T07:09:48.306Z"),
"__v" : 0,
"labelDocuments" : [
{
"_id" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"is_deleted" : false,
"labelName" : "Đông",
"description" : "qw",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:19:35.985Z"),
"updatedAt" : ISODate("2022-04-06T04:19:35.985Z"),
"__v" : 0,
"datanoiseId" : ObjectId("6261318b23a7a590480f92e6")
}
]
}
你看,labels字段有4条记录,而labelDocuments字段只有1条记录?原因是我给图片赋标签的时候,给1张图片赋了很多标签(labelId相同),所以lookup命令只能join 1条记录?那么在这种情况下如何使“labelDocuments 有 4 个记录相同的”标签“字段?请帮助我,谢谢
$lookup
操作可以获得多条记录。在您的数据中,您只有一个 (ObjectId("624d14d76a4e7f001ed5c6ca")
),您的所有标签都引用了它。这就是您在 labelDocuments
数组中只获得一个文档的原因。
如果您的目标是合并标签,您可以添加查询步骤:
{
$addFields: {
mergedLabels: {
$map: {
input: "$labels",
as: "i",
in: {
$mergeObjects: [
"$$i",
{
$first: {
$filter: {
input: "$labelDocuments",
cond: {
$eq: [
"$$this._id",
"$$i.labelId"
]
}
}
}
}
]
}
}
}
}
},
{
$unset: ["labelDocuments", "labels"]
},
像这个例子:playground 1
这是基于@turivishal
的
如果你想把它们放在一个新数组中,就像你说的,你可以改为添加:
{
$addFields: {
labelDocuments: {
$map: {
input: "$labels",
as: "i",
in: {
$mergeObjects: [
{},
{
$first: {
$filter: {
input: "$labelDocuments",
cond: {
$eq: [
"$$this._id",
"$$i.labelId"
]
}
}
}
}
]
}
}
}
}
},
如果您想将标签保留在图像文档下,最好不要 $unwind
,因为这将是一项代价高昂的冗余操作,但正如我所说,这取决于您接下来要做什么。
你应该先放松一下。
db.Image.aggregate([{
$match: {
$and: [{
"datasetId": ObjectId("624d14216a4e7f001ed5c459"),
"is_deleted": false
}]
}
},
{
$unwind: "$lables"
},
{
$lookup: {
from: "Label",
localField: "labels.labelId",
foreignField: "_id",
as: "labelDocuments",
},
},
{
$sort: {
"_id": -1
}
}
])
我下面有一个“图片”集合(注意:labels字段是一个数组,因为1张图片可能有很多标签)
{
"_id" : ObjectId("624d182b6a4e7f001ed5cd9f"),
"is_deleted" : false,
"labels" : [
{
"_id" : ObjectId("627a0fbc12458800209dd69c"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.440625,
"xmax" : 0.2953125,
"ymin" : 0.102083333333333,
"ymax" : 0.366666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69d"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.2546875,
"xmax" : 0.45,
"ymin" : 0.220833333333333,
"ymax" : 0.439583333333333
},
{
"_id" : ObjectId("627a0fbc12458800209dd69e"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.240625,
"xmax" : 0.48125,
"ymin" : 0.208333333333333,
"ymax" : 0.466666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69f"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.275618374558304,
"xmax" : 0.436395759717314,
"ymin" : 0.136470588235294,
"ymax" : 0.404705882352941
}
],
"img_name" : "6917328478506479617.jpg",
"img_originalname" : "frame27406302021-085850.jpg",
"img_desc" : "Cyber Sercurity multi upload",
"img_uri" : "http://localhost:8080/resources/images/2022/4/6/6917328478506479617.jpg",
"img_path" : "/resources/images/2022/4/6/6917328478506479617.jpg",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:33:47.120Z"),
"updatedAt" : ISODate("2022-05-10T07:09:48.306Z"),
"__v" : 0
}
下面是“标签”集合:
{
"_id" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"is_deleted" : false,
"labelName" : "Đông",
"description" : "qw",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:19:35.985Z"),
"updatedAt" : ISODate("2022-04-06T04:19:35.985Z"),
"__v" : 0,
"datanoiseId" : ObjectId("6261318b23a7a590480f92e6")
}
现在我想查找将有关标签的所有信息加入到图像中,所以我这样做了:
db.Image.aggregate([
{
$match: {
$and: [{"datasetId": ObjectId("624d14216a4e7f001ed5c459"), "is_deleted": false}]
}
},
{
$lookup: {
from: "Label",
localField: "labels.labelId",
foreignField: "_id",
as: "labelDocuments",
},
},
{ $sort : { "_id" : -1 } }
])
执行上述查询后得到的结果如下:
{
"_id" : ObjectId("624d182b6a4e7f001ed5cd9f"),
"is_deleted" : false,
"labels" : [
{
"_id" : ObjectId("627a0fbc12458800209dd69c"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.440625,
"xmax" : 0.2953125,
"ymin" : 0.102083333333333,
"ymax" : 0.366666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69d"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.2546875,
"xmax" : 0.45,
"ymin" : 0.220833333333333,
"ymax" : 0.439583333333333
},
{
"_id" : ObjectId("627a0fbc12458800209dd69e"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.240625,
"xmax" : 0.48125,
"ymin" : 0.208333333333333,
"ymax" : 0.466666666666667
},
{
"_id" : ObjectId("627a0fbc12458800209dd69f"),
"labelId" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"xmin" : 0.275618374558304,
"xmax" : 0.436395759717314,
"ymin" : 0.136470588235294,
"ymax" : 0.404705882352941
}
],
"img_name" : "6917328478506479617.jpg",
"img_originalname" : "frame27406302021-085850.jpg",
"img_desc" : "Cyber Sercurity multi upload",
"img_uri" : "http://localhost:8080/resources/images/2022/4/6/6917328478506479617.jpg",
"img_path" : "/resources/images/2022/4/6/6917328478506479617.jpg",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:33:47.120Z"),
"updatedAt" : ISODate("2022-05-10T07:09:48.306Z"),
"__v" : 0,
"labelDocuments" : [
{
"_id" : ObjectId("624d14d76a4e7f001ed5c6ca"),
"is_deleted" : false,
"labelName" : "Đông",
"description" : "qw",
"datasetId" : ObjectId("624d14216a4e7f001ed5c459"),
"createdAt" : ISODate("2022-04-06T04:19:35.985Z"),
"updatedAt" : ISODate("2022-04-06T04:19:35.985Z"),
"__v" : 0,
"datanoiseId" : ObjectId("6261318b23a7a590480f92e6")
}
]
}
你看,labels字段有4条记录,而labelDocuments字段只有1条记录?原因是我给图片赋标签的时候,给1张图片赋了很多标签(labelId相同),所以lookup命令只能join 1条记录?那么在这种情况下如何使“labelDocuments 有 4 个记录相同的”标签“字段?请帮助我,谢谢
$lookup
操作可以获得多条记录。在您的数据中,您只有一个 (ObjectId("624d14d76a4e7f001ed5c6ca")
),您的所有标签都引用了它。这就是您在 labelDocuments
数组中只获得一个文档的原因。
如果您的目标是合并标签,您可以添加查询步骤:
{
$addFields: {
mergedLabels: {
$map: {
input: "$labels",
as: "i",
in: {
$mergeObjects: [
"$$i",
{
$first: {
$filter: {
input: "$labelDocuments",
cond: {
$eq: [
"$$this._id",
"$$i.labelId"
]
}
}
}
}
]
}
}
}
}
},
{
$unset: ["labelDocuments", "labels"]
},
像这个例子:playground 1 这是基于@turivishal
的如果你想把它们放在一个新数组中,就像你说的,你可以改为添加:
{
$addFields: {
labelDocuments: {
$map: {
input: "$labels",
as: "i",
in: {
$mergeObjects: [
{},
{
$first: {
$filter: {
input: "$labelDocuments",
cond: {
$eq: [
"$$this._id",
"$$i.labelId"
]
}
}
}
}
]
}
}
}
}
},
如果您想将标签保留在图像文档下,最好不要 $unwind
,因为这将是一项代价高昂的冗余操作,但正如我所说,这取决于您接下来要做什么。
你应该先放松一下。
db.Image.aggregate([{
$match: {
$and: [{
"datasetId": ObjectId("624d14216a4e7f001ed5c459"),
"is_deleted": false
}]
}
},
{
$unwind: "$lables"
},
{
$lookup: {
from: "Label",
localField: "labels.labelId",
foreignField: "_id",
as: "labelDocuments",
},
},
{
$sort: {
"_id": -1
}
}
])