MongoDB 对嵌套数组的过滤查询

999 阅读2分钟

需求

在一个document里有一个嵌套数组,该数组中里元素众多,如下:

{
    "_id" : ObjectId("6093aa6650b8140013983781"),
    "code" : "22155",
    "subject" : "黄金时间段",
    "status" : "starting",
    "specialist" : [],
    "attendees" : [ 
        {
            "key" : "1",
            "name" : "徐一",
            "role" : "applicant",
            "idcard" : "320481199405131234",
            "iphone" : "1518971234",
        },
        {
            "key" : "2",
            "name" : "徐二",
            "role" : "applicant",
            "idcard" : "320481199405132222",
            "iphone" : "1518972222",
        },
        {
            "key" : "3",
            "name" : "徐三",
            "role" : "applicant",
            "idcard" : "320481199405133333",
            "iphone" : "1518973333",
        }
    ],
}

我需要根据名字和电话号码获取该用户的身份证号码

查询条件是 "attendees.iphone"="1518971234","attendees.name"="徐一"。期望返回的结果如下所示:

{
    "_id" : ObjectId("6093aa6650b8140013983781"),
    "attendees" : [ 
        {
            "key" : "1",
            "name" : "徐一",
            "role" : "applicant",
            "idcard" : "320481199405131234",
            "iphone" : "1518971234",
        }
    ],
}

但是find 的结果,事与愿违,把数组里的全部元素返回给了我

$elemMatch (projection)

elemMatch操作符将查询结果中字段的内容限制为只包含与elemMatch操作符将查询结果中字段的内容限制为只包含与elemMatch条件匹配的第一个元素。

官方Api地址:docs.mongodb.com/manual/refe…

因此,我们可以改造一下find里面的参数

let user = await CaseModal.find({
      "attendees.iphone":phone,
      "attendees.name":name
    },{
      "attendees":{
        $elemMatch:{
          "iphone":phone,
          "name":name
        }
      }
    })

我们终于得到了我们期望的结果

小坑点

但是!!!官方文档里有一句话The $elemMatch operator limits the contents of an <array> field from the query results to contain only the first element matching the $elemMatch condition.意思就是说,只会返回数组所有符合元素的第一位元素.所以,很多场景$elemMatch就不适用于,那该用些什么呢?

Aggregation Pipeline(聚合管道)

聚合操作将来自多个文档的值分组在一起,可以对分组的数据执行各种操作以返回单个结果 具体用法查看官方文档

  • $unwind : 将数组类型的字段进行拆分
  • $match : 过滤数据,只输出符合结果的文档
  • $project: 修改输入文档的结构(例如重命名,增加、删除字段,创建结算结果等)
let user = await CaseModal.aggregate([
      {
        "$unwind":"$attendees"
      },
      {
        "$match":{
          "attendees.iphone":phone,
          "attendees.name":name
        }
      },
      {
        "$project":{
          "attendees" : 1
        }
      }
    ])
{
    "success": true,
    "data": [
        {
            "_id": "604f1e7a63f9ff00126332fc",
            "attendees": {
                "name": "当事人1",
                "role": "applicant",
                "idcard": "123",
                "iphone": "123",
                "password": "123456",
                "inviteCode": "123456"
            }
        },
        {
            "_id": "604f201a63f9ff00126332fe",
            "attendees": {
                "name": "当事人1",
                "role": "applicant",
                "idcard": "123",
                "iphone": "123",
                "password": "123456",
                "inviteCode": "123456"
            }
        }
    ]
}

得到了我们期望的结果

总结

学习东西,一定要多多查看官方文档,读懂文档,才能正确使用,如果遇到全英文的看不懂的,可以多看几篇别人整理的中文文档,同时也要对照着官方文档,自己做一些整理.这样才能让自己进步哦.加油!