在 mongodb 中过滤多级数组集合
filtering a multi-level array collection in mongodb
在 mongoDB 中,如何编写过滤 postcode、student name 和 [=23] 的查询=]subjId 来自这个多级数组?我正在使用 mongoskin
和 ExpressJS
。这是数据结构
[{
"_id": "1",
"postcode": "SE41TB",
"students": [{
"name": "ajax",
"school": "100",
"age": "7",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}, {
"name": "backbone",
"school": "100",
"age": "8",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}]
}, {
"_id": "2",
"postcode": "SEI3BT",
"students": [{
"name": "jquery",
"school": "100",
"age": "7",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}, {
"name": "angular",
"school": "100",
"age": "8",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}]
}]
这是我目前所掌握的 student name
,但我不知道如何添加 subjId 过滤器 -
db.collection('test').find({
'postcode': postcode
}, {
'students': {
$elemMatch: {
'name': name
}
}
});
提前致谢。
您可以使用聚合来获得预期结果。
建议避免复杂的嵌套文档结构。
您可以尝试以下聚合查询:
db.collection.aggregate({
"$match": {
"postcode": "SE41TB"
}
}, {
"$unwind": "$students"
}, {
"$match": {
"students.name": "ajax"
}
}, {
"$unwind": "$students.subjects"
}, {
"$match": {
"students.subjects.subjId": "1"
}
}, {
"$group": {
"_id": {
"postcode": "$postcode"
},
"name": {
"$first": "$students.name"
},
"school": {
"$first": "$students.school"
},
"age": {
"$first": "$students.age"
},
"subjects": {
"$push": "$students.subjects"
}
}
}, {
"$group": {
"_id": "$name",
"students": {
"$push": {
"name": "$name",
"school": "$school",
"age": "$age",
"subjects": "$subjects"
}
}
}
})
使用$setDifference and $map可以找到如下匹配结果:
db.collectionName.aggregate({
"$match": {
"postcode": "SEI3BT" //match given post code
}
}, {
"$project": {
"checkStudentsName": {
"$setDifference": [{
"$map": { //$map iterate over students array and first match studentsDetails.name as given name
"input": "$students",
"as": "studentsDetails",
"in": {
"$cond": {
"if": {
"$eq": ["$$studentsDetails.name", "jquery"]
},
"then": "$$studentsDetails",
"else": false
}
}
}
},
[false]
]
}
}
}, {
"$unwind": "$checkStudentsName" // this unwind used for unwinding the matched array
}, {
"$project": {
"name": "$checkStudentsName.name",
"school": "$checkStudentsName.school",
"age": "$checkStudentsName.age",
"subjects": "$checkStudentsName.subjects"
}
}, {
"$project": {
"name": 1,
"school": 1,
"age": 1,
"subjects": {
"$setDifference": [{
"$map": { // this $map iterate over subjects array and first match subjectDetails.subjId as given subjId
"input": "$subjects",
"as": "subjectDetails",
"in": {
"$cond": {
"if": {
"$eq": ["$$subjectDetails.subjId", "1"]
},
"then": "$$subjectDetails",
"else": false
}
}
}
},
[false]
]
}
}
}).pretty()
在 mongoDB 中,如何编写过滤 postcode、student name 和 [=23] 的查询=]subjId 来自这个多级数组?我正在使用 mongoskin
和 ExpressJS
。这是数据结构
[{
"_id": "1",
"postcode": "SE41TB",
"students": [{
"name": "ajax",
"school": "100",
"age": "7",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}, {
"name": "backbone",
"school": "100",
"age": "8",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}]
}, {
"_id": "2",
"postcode": "SEI3BT",
"students": [{
"name": "jquery",
"school": "100",
"age": "7",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}, {
"name": "angular",
"school": "100",
"age": "8",
"subjects": [{
"subjId": "1",
"subjName": "Maths"
}, {
"subjId": "2",
"subjName": "English"
}]
}]
}]
这是我目前所掌握的 student name
,但我不知道如何添加 subjId 过滤器 -
db.collection('test').find({
'postcode': postcode
}, {
'students': {
$elemMatch: {
'name': name
}
}
});
提前致谢。
您可以使用聚合来获得预期结果。
建议避免复杂的嵌套文档结构。
您可以尝试以下聚合查询:
db.collection.aggregate({
"$match": {
"postcode": "SE41TB"
}
}, {
"$unwind": "$students"
}, {
"$match": {
"students.name": "ajax"
}
}, {
"$unwind": "$students.subjects"
}, {
"$match": {
"students.subjects.subjId": "1"
}
}, {
"$group": {
"_id": {
"postcode": "$postcode"
},
"name": {
"$first": "$students.name"
},
"school": {
"$first": "$students.school"
},
"age": {
"$first": "$students.age"
},
"subjects": {
"$push": "$students.subjects"
}
}
}, {
"$group": {
"_id": "$name",
"students": {
"$push": {
"name": "$name",
"school": "$school",
"age": "$age",
"subjects": "$subjects"
}
}
}
})
使用$setDifference and $map可以找到如下匹配结果:
db.collectionName.aggregate({
"$match": {
"postcode": "SEI3BT" //match given post code
}
}, {
"$project": {
"checkStudentsName": {
"$setDifference": [{
"$map": { //$map iterate over students array and first match studentsDetails.name as given name
"input": "$students",
"as": "studentsDetails",
"in": {
"$cond": {
"if": {
"$eq": ["$$studentsDetails.name", "jquery"]
},
"then": "$$studentsDetails",
"else": false
}
}
}
},
[false]
]
}
}
}, {
"$unwind": "$checkStudentsName" // this unwind used for unwinding the matched array
}, {
"$project": {
"name": "$checkStudentsName.name",
"school": "$checkStudentsName.school",
"age": "$checkStudentsName.age",
"subjects": "$checkStudentsName.subjects"
}
}, {
"$project": {
"name": 1,
"school": 1,
"age": 1,
"subjects": {
"$setDifference": [{
"$map": { // this $map iterate over subjects array and first match subjectDetails.subjId as given subjId
"input": "$subjects",
"as": "subjectDetails",
"in": {
"$cond": {
"if": {
"$eq": ["$$subjectDetails.subjId", "1"]
},
"then": "$$subjectDetails",
"else": false
}
}
}
},
[false]
]
}
}
}).pretty()