【问题标题】:How to make a mongodb query with nested arrays如何使用嵌套数组进行 m​​ongodb 查询
【发布时间】:2022-01-10 04:34:14
【问题描述】:

我有一个 mongo db 集合,其中每个文档都有两个嵌套数组(每个文档都有一个存储数组的元素,该数组存储存储另一个数组的文档),我只想要最深文档的一些字段。我尝试了不同类型的投影元素,但都没有奏效。现在我正在尝试以下方法:

let answered_exam = await exams_table.findOne(
{_id: new ObjectId(req.body.course_id)}, 
{projection: { 
  _id: 1, 
  "exams": {
    "$map": {
      "input": "$exams",
      "in": { 
        "$this.exam_name": req.body.exam_name,
        "students_exams": {  
          "$map": {
            "input": "$$this.students_exams",
            "in": { "student_email": req.body.student_email },
        }},
      },
    }}
  } 
});

数据库中条目的格式如下: 中间的属性块是存储在考试数组中的文档 (每个元素都是这样的)。下面的块是文档的格式。

【问题讨论】:

  • 你的画是我见过的最好的,但是文本 JSON 更容易,所以人们可以测试他们的查询

标签: mongodb mongodb-query


【解决方案1】:

查询1
(放松)

  • 您可以进行嵌套映射和过滤,但这里我们只选择 1 个考试 所以我猜数据很小,为了简单起见,我们可以使用双重展开
  • 匹配_id
  • 放松exams
  • 匹配exam_name
  • 放松student_exams
  • 匹配email
  • 项目只保留professor_notesmark
  • 如果您只想要最多 1 个结果,最后还要添加一个阶段
    {"limit" : 1}

Test code here

aggregate(
[{"$match": {"$expr": {"$eq": ["$_id", 1]}}},
  {"$unwind": {"path": "$exams"}},
  {"$match": {"$expr": {"$eq": ["$exams.exam_name", "exam1"]}}},
  {"$unwind": {"path": "$exams.student_exams"}},
  {"$match": 
    {"$expr": {"$eq": ["$exams.student_exams.student_email", "email1"]}}},
  {"$project": 
    {"_id": 0,
      "professor_notes": "$exams.student_exams.professor_notes",
      "mark": "$exams.student_exams.mark"}}])

查询2
(嵌套地图/过滤器)

  • map if not match null else map 再次做同样的事情
  • 在返回过滤器上删除空值
  • 获取第一个,第一个并替换根

*查询很大,它做同样的事情,映射而不是展开,过滤而不是匹配(2 map/2 unwind,2 filter/2 match)

Test code here

aggregate(
[{"$match": {"$expr": {"$eq": ["$_id", 1]}}},
  {"$replaceRoot": 
    {"newRoot": 
      {"$arrayElemAt": 
        [{"$arrayElemAt": 
            [{"$filter": 
                {"input": 
                  {"$map": 
                    {"input": "$exams",
                      "in": 
                      {"$cond": 
                        [{"$not": [{"$eq": ["$$exam.exam_name", "exam1"]}]}, null,
                          {"$filter": 
                            {"input": 
                              {"$map": 
                                {"input": "$$exam.student_exams",
                                  "in": 
                                  {"$cond": 
                                    [{"$not": 
                                        [{"$eq": 
                                            ["$$students_exam.student_email", "email1"]}]},
                                      null,
                                      {"professor_notes": 
                                        "$$students_exam.professor_notes",
                                        "mark": "$$students_exam.mark"}]},
                                  "as": "students_exam"}},
                              "cond": {"$ne": ["$$students_exam", null]},
                              "as": "students_exam"}}]},
                      "as": "exam"}},
                  "cond": {"$ne": ["$$exam", null]},
                  "as": "exam"}}, 0]}, 0]}}}])

【讨论】:

  • 你为什么使用$expr?只需使用{$match: {_id: 1}}{$match: {"exams.exam_name": "exam1"}}{$match: {"exams.student_exams.student_email": "email1"}}?
  • 我不是手工写的,而且在我的库中代码同样复杂,所以我有时会忘记使用更简单的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 2021-01-22
  • 2012-05-04
相关资源
最近更新 更多