首页 > 解决方案 > $elemMatch 不适用于 MongoDB 中的嵌套文档

问题描述

堆栈溢出!

在 MongoDB中使用$elemMatch有一个非常奇怪的问题。我将多个文档添加到集合中。其中一些文档是使用MongoDB Compass 中的导入功能添加的(添加数据 -> 导入文件 -> JSON),其中一些是使用insertMany()添加的。以下是单个文档的示例结构:

{
    "id": "1234567890",
    "date": "YYYY-MM-DD",
    "contents": {
        "0": {
            "content": {
                "id": "1111111111",
                "name": "Name 1"
            }
        },
        "1": {
            "content": {
                "id": "2222222222",
                "name": "Name 2"
            }
        },
        "2": {
            "content": {
                "id": "3333333333",
                "name": "Name 3"
            }
        }
    }
}

问题是,当我使用此过滤器使用以下查找查询时:

{date: "<some_date_here>", "contents": {
    $elemMatch: {
        "content.id": <some_id_here>
    }
}}

显示从 MongoDB Compass 导入的文档。由 Mongosh 或 NodeJS 驱动程序(无关紧要)添加的文档不会显示

我在这里遗漏了一些明显的东西吗?我应该怎么做才能显示集合中的所有文档(匹配过滤器)?

不包含 $elemMatch 的简单过滤器运行良好,所有符合过滤规则的文档都会显示出来。问题似乎出在 $elemMatch 上。

我尝试使用不同的方法添加同一批文档,但仅在 MongoDB Compass 中直接导入 JSON 文件使它们使用上述过滤器出现。

谢谢您的帮助!

标签: mongodb

解决方案


$elemMatch如果用于匹配数组,在这种情况下,您首先没有数组,您应该将contents对象转换为数组,然后检查查询,例如 idfilter并用于match查找所有具有特定数据和新过滤器数组大小的文档

db.collection.aggregate([
  {
    "$addFields": {
      "newField": {
        "$objectToArray": "$contents"
      }
    }
  },
  {
    "$addFields": {
      "newField": {
        "$filter": {
          "input": "$newField",
          "as": "z",
          "cond": {
            $eq: [
              "$$z.v.content.id",
              "1111111111"
            ]
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "newField": {
        $size: "$newField"
      }
    }
  },
  {
    $match: {$and:[ {newField: {
        $gt: 0
      }},{date:{$gt:Date}}]}
     
    
  },
  {$project:{
    contents:1,
    date:1,
    id:1,
  }}
])

https://mongoplayground.net/p/pue4QPp1dYR 在 mongoplayground 我不添加日期过滤器


推荐阅读