英文:
How to Modify MongoDB Object Located in an Array that is Nested in Another Array?
问题
以下是翻译的部分:
我遇到一个问题,我需要修改位于数组中的特定对象的特定字段,但我需要在另一个数组中过滤出该对象。例如,假设我有以下文档:
{
_id: '1',
name: 'Plan',
builds: [
{
_id: '11',
number: 20,
type: 'Test Object 1',
artifacts: [
{
link: 'helloworld.com',
minioPath: 'test.zip',
_id: '111'
},
{
link: 'helloworld.com',
minioPath: 'test15.zip',
__id: '112'
}
]
},
{
_id: '12',
number: 21,
type: 'Test Object 2',
artifacts: [
{
link: 'mongo.com',
minioPath: 'test20.zip',
_id: '211'
},
{
link: 'mongo.com',
minioPath: 'test25.zip',
_id: '212'
}
]
}
]
}
我想要做以下操作:
1)从“builds”数组中过滤出特定的“build”对象。
2)从“artifacts”数组中过滤出特定的“artifact”对象。
3)将“minioPath”字段更新为所需的值。
对于这个问题,我正在使用NestJS中的MongoDB来构建聚合管道。以下是我目前的代码:
async getBuildItemArtifacts(id: string, buildItemId: string) {
const buildPlanCondition = isMongoId(id)
? { _id: new Types.ObjectId(id) }
: { key: id };
const matchStage: PipelineStage.Match = { $match: buildPlanCondition };
const filterBuildStage: PipelineStage[] = [
{
$project: {
builds: {
artifacts: {
$filter: {
input: '$artifacts',
as: 'artifact',
cond: {
$eq: [
'$$artifact._id',
new Types.ObjectId('111'),
],
},
},
},
},
},
},
];
const {
builds: [result],
} = await this.builds
.aggregate<Partial<Build>>([matchStage, ...filterBuildStage])
.then(([doc]) => {
if (_.isUndefined(doc) || _.isEmpty(doc?.builds)) {
throw new ApiError(HttpStatus.NOT_FOUND, 'No data found');
}
return doc;
});
return result;
}
到目前为止,我能够过滤出特定的“build”对象,但我不确定如何继续过滤出特定的“artifact”对象。聚合管道变得有点混乱,所以任何建议将不胜感激!
英文:
I have the problem where I need to modify a specific field of a object that is located in a array, but I would need to filter out the object within another array to get that specific object. For example, lets say I have the following document:
{
_id: '1'
name: 'Plan',
builds: [
{
_id: '11'
number: 20,
type: 'Test Object 1',
artifacts: [
{
link: 'helloworld.com',
minioPath: 'test.zip'
_id: '111'
},
{
link: 'helloworld.com',
minioPath: 'test15.zip',
_id: '112'
}
]
},
{
_id: '12'
number: 21,
type: 'Test Object 2',
artifacts: [
{
link: 'mongo.com',
minioPath: 'test20.zip',
_id: '211'
},
{
link: 'mongo.com',
minioPath: 'test25.zip',
_id: '212'
}
]
}
]
}
What I would like to do is the following:
- Filter out the specific
build
object from thebuilds
array. - Filter out the specific
artifact
object from theartifacts
array. - Update the
minioPath
field to desired value.
For this problem, I am using MongoDB in NestJS to build an aggregation pipeline. This is what I have so far:
async getBuildItemArtifacts(id: string, buildItemId: string) {
const buildPlanCondition = isMongoId(id)
? { _id: new Types.ObjectId(id) }
: { key: id };
const matchStage: PipelineStage.Match = { $match: buildPlanCondition };
const filterBuildStage: PipelineStage[] = [
{
$project: {
builds: {
artifacts: {
$filter: {
input: '$artifacts',
as: 'artifact',
cond: {
$eq: [
'$$artifact._id',
new Types.ObjectId('111'),
],
},
},
},
},
},
},
];
const {
builds: [result],
} = await this.builds
.aggregate<Partial<Build>>([matchStage, ...filterBuildStage])
.then(([doc]) => {
if (_.isUndefined(doc) || _.isEmpty(doc?.builds)) {
throw new ApiError(HttpStatus.NOT_FOUND, 'No data found');
}
return doc;
});
return result;
}
So far, I'm able to filter out the specific build
object, but I'm now sure how to go about filtering out the specific artifact
object. The aggregation pipeline got a little confusing, so any advice would be much appreciated!
答案1
得分: 0
filtering out the specific artifact object
to filter out of them
db.collection.aggregate([
{
"$match": {
_id: "64011d1c2839dd1845354dfb"
}
},
{
$project: {
"builds": {
"$filter": {
"input": {
"$map": {
"input": "$builds",
"as": "build",
"in": {
"_id": "$$build._id",
"artifacts": {
"$filter": {
"input": "$$build.artifacts",
"as": "artifact",
"cond": {
$eq: [
"$$artifact._id",
"64011d302839dd1845354e00"
]
}
}
}
}
}
},
"as": "build",
"cond": {
"$ne": [
"$$build.artifacts",
[]
]
}
}
},
},
},
])
here how to update
db.collection.update({
"_id": "64011d1c2839dd1845354dfb",
"builds._id": "64011d302839dd1845354dfe",
},
{
$set: {
"builds.$.artifacts.$[elem].minioPath": "mini mini"
},
},
{
"arrayFilters": [
{
"elem._id": "64011d302839dd1845354e00"
}
]
})
英文:
filtering out the specific artifact object
to filter out of them
db.collection.aggregate([
{
"$match": {
_id: "64011d1c2839dd1845354dfb"
}
},
{
$project: {
"builds": {
"$filter": {
"input": {
"$map": {
"input": "$builds",
"as": "build",
"in": {
"_id": "$$build._id",
"artifacts": {
"$filter": {
"input": "$$build.artifacts",
"as": "artifact",
"cond": {
$eq: [
"$$artifact._id",
"64011d302839dd1845354e00",
]
}
}
}
}
}
},
"as": "build",
"cond": {
"$ne": [
"$$build.artifacts",
[]
]
}
}
},
},
},
])
here how to update
db.collection.update({
"_id": "64011d1c2839dd1845354dfb",
"builds._id": "64011d302839dd1845354dfe",
},
{
$set: {
"builds.$.artifacts.$[elem].minioPath": "mini mini"
},
},
{
"arrayFilters": [
{
"elem._id": "64011d302839dd1845354e00"
}
]
})
答案2
得分: 0
The update
is pretty easy using "arrayFilters"
.
db.collection.update({
_id: "1"
},
{
"$set": {
"builds.$[buildElem].artifacts.$[artElem].minioPath": "test42.zip"
}
},
{
"arrayFilters": [
{"buildElem._id": "11"},
{"artElem._id": "111"}
]
})
Try it on mongoplayground.net.
英文:
The update
is pretty easy using "arrayFilters"
.
db.collection.update({
_id: "1"
},
{
"$set": {
"builds.$[buildElem].artifacts.$[artElem].minioPath": "test42.zip"
}
},
{
"arrayFilters": [
{"buildElem._id": "11"},
{"artElem._id": "111"}
]
})
Try it on [mongoplayground.net](https://mongoplayground.net/p/UWuEwjmns8L "Click me!").
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论