如何将对象列表转换为对象的外部新对象?
How to transform a list of objects into an outer new object of objects?
鉴于此课程集合,有一个由对象组成的主题列表。是否可以创建一个聚合来创建一个新字段 newSubjects
以通过其 ID 映射所有主题?例如,给定此集合如何将 subjects
条目从 :
[
{
_id: ObjectId("623e2f0cb242ee9367eb3c9f"),
subjects: [ { id: '1', name: 'math' }, { id: '2', name: 'physics' } ]
},
{
_id: ObjectId("623e2f17b242ee9367eb3ca0"),
subjects: [ { id: '1', name: 'math' }, { id: '3', name: 'biology' } ]
}
]
进入:
{
newSubjects: { '1': { id: '1', name: 'math' }, '2': { id: '2', name: 'physics' } }
}
{
newSubjects: { '1': { id: '1', name: 'math' }, '3': { id: '3', name: 'biology' } }
}
使用 JavaScript 我可以用这个表达式来做:
db.courses.find().forEach(x => print({"newSubjects": Object.fromEntries(new Map(x.subjects.map(s => [s.id, s])))}))
我正在尝试找出一个聚合来完成此操作,但 $addField
和 $map
尚未成功。
您可以试试这个查询:
只需要一个聚合阶段就可以合成你想要的结果。在此阶段,您可以使用 $map
对每个值进行迭代,并使用 return 一个新值。这个新的将有 k
和 v
字段。
k
字段将是对象键 (1, 2, 3...)
v
字段将是值字段(具有 {id:..., name:...} 的对象)
并由 $arrayToObject
包装以将 k
和 v
翻译成所需的对象。
db.collection.aggregate([
{
"$project": {
"_id": 0,
"newSubjects": {
"$arrayToObject": {
"$map": {
"input": "$$ROOT.subjects",
"in": {
"k": "$$this.id",
"v": {
"id": "$$this.id",
"name": "$$this.name"
}
}
}
}
}
}
}
])
示例here
另一个选项:
db.collection.aggregate([
{
"$project": {
"newSubjects": {
"$arrayToObject": {
"$map": {
"input": "$subjects",
"as": "s",
"in": {
k: "$$s.id",
v: "$$s"
}
}
}
}
}
}
])
解释:
用适合 arrayToObject 投影为 newSubjects 的必要 k,v 映射数组
鉴于此课程集合,有一个由对象组成的主题列表。是否可以创建一个聚合来创建一个新字段 newSubjects
以通过其 ID 映射所有主题?例如,给定此集合如何将 subjects
条目从 :
[
{
_id: ObjectId("623e2f0cb242ee9367eb3c9f"),
subjects: [ { id: '1', name: 'math' }, { id: '2', name: 'physics' } ]
},
{
_id: ObjectId("623e2f17b242ee9367eb3ca0"),
subjects: [ { id: '1', name: 'math' }, { id: '3', name: 'biology' } ]
}
]
进入:
{
newSubjects: { '1': { id: '1', name: 'math' }, '2': { id: '2', name: 'physics' } }
}
{
newSubjects: { '1': { id: '1', name: 'math' }, '3': { id: '3', name: 'biology' } }
}
使用 JavaScript 我可以用这个表达式来做:
db.courses.find().forEach(x => print({"newSubjects": Object.fromEntries(new Map(x.subjects.map(s => [s.id, s])))}))
我正在尝试找出一个聚合来完成此操作,但 $addField
和 $map
尚未成功。
您可以试试这个查询:
只需要一个聚合阶段就可以合成你想要的结果。在此阶段,您可以使用 $map
对每个值进行迭代,并使用 return 一个新值。这个新的将有 k
和 v
字段。
k
字段将是对象键 (1, 2, 3...)v
字段将是值字段(具有 {id:..., name:...} 的对象)
并由 $arrayToObject
包装以将 k
和 v
翻译成所需的对象。
db.collection.aggregate([
{
"$project": {
"_id": 0,
"newSubjects": {
"$arrayToObject": {
"$map": {
"input": "$$ROOT.subjects",
"in": {
"k": "$$this.id",
"v": {
"id": "$$this.id",
"name": "$$this.name"
}
}
}
}
}
}
}
])
示例here
另一个选项:
db.collection.aggregate([
{
"$project": {
"newSubjects": {
"$arrayToObject": {
"$map": {
"input": "$subjects",
"as": "s",
"in": {
k: "$$s.id",
v: "$$s"
}
}
}
}
}
}
])
解释:
用适合 arrayToObject 投影为 newSubjects 的必要 k,v 映射数组