我有一份如下文件
{
"_id" : ObjectId("58b..."),
"job" : "Plumber",
"properties": [
{
"name" : "First_Name",
"values": [
"John"
]
},
{
"name" : "Last_Name",
"values": [
"Smith"
]
},
{
"name" : "Age",
"values": [
"28"
]
},
{
"name" : "Gender",
"values": [
"male"
]
},
{
"name" : "Phone_Number",
"values": [
"12345"
]
},
{
"name" : "city",
"values": [
"NY"
]
}
]
}
我需要一个mongodb聚合查询来获取如下文档
{
"job" : "Plumber",
"Name" : "John Smith",
"Age" : 20,
"Gender" : "male"
}
答案 0 :(得分:1)
我不认为它很好地利用了聚合,但无论如何它仍然存在:
db.sample.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$let": {
"vars": {
// Make a copy of the array reshaped
"props": {
"$map": {
"input": "$properties",
"as": "p",
"in": {
"k": "$$p.name",
"v": { "$arrayElemAt": [ "$$p.values", 0 ] }
}
}
}
},
"in": {
"$arrayToObject": { // Converts k and v array to object
"$concatArrays": [
[
// Plain field object
{ "k": "job", "v": "$job" },
// Join First_Name and Last_Name into one string
{
"k": "name",
"v": {
"$concat": [
{ "$arrayElemAt": [
"$$props.v",
{ "$indexOfArray": [ "$$props.k", "First_Name" ] }
]},
" ",
{ "$arrayElemAt": [
"$$props.v",
{ "$indexOfArray": [ "$$props.k", "Last_Name" ] }
]},
]
}
}
],
// Exclude First_Name and Last_Name entries from the array
{ "$filter": {
"input": "$$props",
"cond": { "$not": { "$in": [ "$$this.k", ["First_Name","Last_Name"] ] } }
}}
]
}
}
}
}
}}
])
在客户端代码中,这与shell示例相同:
db.sample.find().map( doc =>
Object.assign(
// Just assign the plain field, to "merge" with:
{ job: doc.job },
// Joined array of two parts
[].concat.apply(
// Join First_Name and Last_Name entries in a single item
[{
"k": "name",
"v": doc.properties.map(p => ({ k: p.name, v: p.values[0] }) )
.filter(p => ["First_Name","Last_Name"].indexOf(p.k) !== -1 )
.map( p => p.v).join(" ")
}],
// Exclude First_Name and Lasst_Name entries from array
doc.properties.map(p => ({ k: p.name, v: p.values[0] }) )
.filter(p => ["First_Name","Last_Name"].indexOf(p.k) === -1 )
)
// Map keys and values
.map( p => ({ [p.k]: p.v }))
// Reduce array into single object
.reduce((acc,curr) => Object.assign(acc,curr),{})
)
)
两者都产生:
{
"job" : "Plumber",
"name" : "John Smith",
"Age" : "28",
"Gender" : "male",
"Phone_Number" : "12345",
"city" : "NY"
}
所以通常说这不是你使用.aggregate()
的原因,因为你只需编写代码来处理游标上的结构变化。但是,如果您需要"稍后聚合"的格式,那么请继续这样做。