过滤mongodb

时间:2015-08-06 11:51:50

标签: mongodb mongoskin

在mongoDB中,如何编写一个过滤来自此多级数组的邮政编码学生姓名 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
    }
    }
});

提前致谢。

2 个答案:

答案 0 :(得分:1)

您可以使用聚合来获得预期结果。

建议避免使用复杂的嵌套文档结构。

您可以尝试以下聚合查询:

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"
        }
    }
    }
})

答案 1 :(得分:0)

使用$setDifference$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()