mongodb多个匹配条件并返回具有通用名称的文档

Posted

技术标签:

【中文标题】mongodb多个匹配条件并返回具有通用名称的文档【英文标题】:mongodb multiple match conditions and return documents with common name 【发布时间】:2018-08-09 09:02:07 【问题描述】:

以下数据存在于“examSheet”集合中

"name":"a1", "std":"9", "year":"2017", "exam":"halfyr_T", "marks":["p":"45","m":"40","c":"50"]
"name":"a1", "std":"9", "year":"2017", "exam":"halfyr_P", "marks":["p":"40","m":"28","c":"38"]
"name":"a1", "std":"9", "year":"2017", "exam":"annual_T", "marks":["p":"40","m":"50","c":"48"]
"name":"a1", "std":"9", "year":"2017", "exam":"annual_P", "marks":["p":"45","m":"42","c":"18"]
"name":"a2", "std":"9", "year":"2017", "exam":"halfyr_T", "marks":["p":"25","m":"30","c":"50"]
"name":"a2", "std":"9", "year":"2017", "exam":"halfyr_P", "marks":["p":"41","m":"48","c":"28"]
"name":"a2", "std":"9", "year":"2017", "exam":"annual_T", "marks":["p":"30","m":"48","c":"24"]
"name":"a2", "std":"9", "year":"2017", "exam":"annual_P", "marks":["p":"35","m":"08","c":"38"]
"name":"b1", "std":"10", "year":"2017", "exam":"halfyr_T","marks":["p":"45","m":"40","c":"50"]
"name":"b1", "std":"10", "year":"2017", "exam":"halfyr_P", "marks": ["p":"40","m":"28","c":"38"]
"name":"b1", "std":"10", "year":"2017", "exam":"annual_T", "marks": ["p":"40","m":"50","c":"48"]
"name":"b1", "std":"10", "year":"2017", "exam":"annual_P", "marks": ["p":"45","m":"42","c":"18"]
"name":"b2", "std":"10", "year":"2017", "exam":"halfyr_T", "marks": ["p":"25","m":"30","c":"50"]
"name":"b2", "std":"10", "year":"2017", "exam":"halfyr_P", "marks": ["p":"41","m":"48","c":"28"]
"name":"b2", "std":"10", "year":"2017", "exam":"annual_T", "marks": ["p":"30","m":"48","c":"24"]
"name":"b2", "std":"10", "year":"2017", "exam":"annual_P", "marks": ["p":"35","m":"08","c":"38"]

...

我想返回聚合的 json 输出,其中名称满足所有条件。 例如:std:9,year:2017,exam:halfyr_Theory,物理分数 > 25 和 标准:9,年份:2017,考试:年度_理论,物理分数 > 35

我尝试了以下不同的方法, 符合条件, 能够获取“名称”,但无法再次匹配/提取文档数据。

db.examSheet.aggregate([$facet: 
    'halfyr': [ $match: $and: ['exam': 'halfyr_T','std': '9','year': "2017",'marks.p': $gte: '25']],
    "annual": [ $match: $and: ['exam': 'annual_T','std': '9','year': "2017",'marks.p': $gte: '35']] 
    
,
$project: '_id': 0, "combined": $setIntersection: ['$halfyr.name', '$annual.name']
                    ]);

尝试,在项目等之后将 halfyr.name 与 $in [combined] 匹配。 但无法解决问题。

请帮助或建议我解决这个问题。

我试过这个方法。

db.examSheet.aggregate([$facet: 
                            "halfyr": [ $match: $and: ['exam': 'halfyr_T','std': '9','year': "2017",'marks.p': $gte: '25']],
                            "annual": [ $match: $and: ['exam': 'annual_T','std': '9','year': "2017",'marks.p': $gte: '35']] 
                            
                    ,
                    $unwind : "$annual"
                ]);

我的输出是:


    "halfyr" : [
            
                    "_id" : ObjectId("5a98c639b0ae80e6c6a92031"),
                    "name" : "a1",
                    "std" : "9",
                    "year" : "2017",
                    "exam" : "halfyr_T",
                    "marks" : [
                            
                                    "p" : "45",
                                    "m" : "40",
                                    "c" : "50"
                            
                    ]
            ,
            
                    "_id" : ObjectId("5a98c639b0ae80e6c6a9203e"),
                    "name" : "a2",
                    "std" : "9",
                    "year" : "2017",
                    "exam" : "halfyr_T",
                    "marks" : [
                            
                                    "p" : "25",
                                    "m" : "30",
                                    "c" : "50"
                            
                    ]
            
    ],
    "annual" : 
            "_id" : ObjectId("5a98c639b0ae80e6c6a92038"),
            "name" : "a1",
            "std" : "9",
            "year" : "2017",
            "exam" : "annual_T",
            "marks" : [
                    
                            "p" : "40",
                            "m" : "50",
                            "c" : "48"
                    
            ]
    

谁能建议如何匹配或过滤掉半年和年度中常​​见的名字? 提前致谢!!

期望的输出:


"name":"a1", "std":"9", "year":"2017",
"halfyr" : "exam":"halfyr_T", "marks": ["p":"45","m":"40","c":"50"],
"annual" : "exam":"annual_T", "marks": ["p":"40","m":"50","c":"48"]

【问题讨论】:

【参考方案1】:

我使用一些额外的文档计数解决了这个问题。

感谢大家的宝贵时间和建议!

db.examSheet.aggregate([
 
  "$match":
    "$and":[
      "$or":[
        "exam":"halfyr_T","marks.p":"$gte":"25",
        "exam":"annual_T","marks.p":"$gte":"35"
      ],
      "std":"9",
      "year":"2017"
    ]
 ,
 $group: 
        "_id": 
            "code": "$name",
            "type":  "$cond": [ 
                 "$and":[
                     "$gte": [ "$marks.p", 25 ] ,
                     "$eq": [ "$exam", "halfyr_T" ] 
                ],
                "A",
                "B"
            ]
        ,
        "all_data" : $addToSet : "$$ROOT"
    ,
        // Simply add up the results for each "type"
     "$group": 
        "_id": "$_id.code",
        "all_data" : $addToSet : "$all_data",
        "score":  "$sum": 1 
    ,
        // Now filter to keep only results with score 2
     "$match":  "score": 2 ,
    $project : _id :0 , all_data : 1
]);

【讨论】:

【参考方案2】:

您可以使用$or。在$and里面。

db.examSheet.aggregate([
 
  "$match":
    "$and":[
      "$or":[
        "exam":"halfyr_T","marks.p":"$gte":"25",
        "exam":"annual_T","marks.p":"$gte":"35"
      ],
      "std":"9",
      "year":"2017"
    ]
 
])

【讨论】:

$or - 即使条件之一匹配也会给出结果。如果我使用 $and - 我没有输出。感谢您的建议。但我的问题仍然存在。 Yw。更新了答案。 这有帮助。谢谢。它给出了所有匹配的文件。但是我怎样才能过滤掉符合这两个条件的名字呢?任何想法?我尝试了 $match、$push、$eq 等,但没有得到想要的输出。

以上是关于mongodb多个匹配条件并返回具有通用名称的文档的主要内容,如果未能解决你的问题,请参考以下文章

仅获取 mongodb 集合中具有条件的第一个匹配文档

MongoDB查询以获取与具有多个值的键匹配的所有文档[重复]

如何在 MongoDB 中搜索动态字段并首先对最佳匹配结果进行排序

在 R dplyr 中过滤具有多个条件名称匹配的数据框

MongoDB通过***属性和嵌套数组键查找文档,并返回匹配文档的一部分

MongoDB-5: 查询(游标操作游标信息)