【问题标题】:How to query on embedded documents如何查询嵌入的文档
【发布时间】:2021-02-21 09:19:39
【问题描述】:
{
    "_id" : ObjectId("5fa919a49bbe481d117506c9"),
    "isDeleted" : 0,
    "productId" : 31,
    "references" : [ 
        {
            "_id" : ObjectId("5fa919a49bbe481d117506ca"),
            "languageCode" : "en",
            "languageId" : 1,
            "productId" : ObjectId("5fa919a49bbe481d117506ba")
        }, 
        {
            "_id" : ObjectId("5fa91cc7d7d52f1e389dee1f"),
            "languageCode" : "ar",
            "languageId" : 2,
            "productId" : ObjectId("5fa91cc7d7d52f1e389dee1e")
        }
    ],
    "createdAt" : ISODate("2020-11-09T10:27:48.859Z"),
    "updatedAt" : ISODate("2020-11-09T10:27:48.859Z"),
    "__v" : 0
},

{
    "_id" : ObjectId("5f9aab1d8e475489270ebe3a"),
    "isDeleted" : 0,
    "productId" : 21,
    "references" : [ 
        {
            "_id" : ObjectId("5f9aab1d8e475489270ebe3b"),
            "languageCode" : "en",
            "languageId" : 1,
            "productId" : ObjectId("5f9aab1c8e475489270ebe2d")
        }
    ],
    "createdAt" : ISODate("2020-10-29T11:44:29.852Z"),
    "updatedAt" : ISODate("2020-10-29T11:44:29.852Z"),
    "__v" : 0
}

这是我的 mongoDB 集合,我在其中存储对产品集合的多语言引用。在 productId 中是对产品集合的引用。现在如果我们的请求中有 ar,那么我们将只有 ar 语言代码的 productId。如果该语言代码不存在,那么我们将有 en langCode productId。

例如,如果用户传递了 ar,那么查询应该返回

 "productId" : ObjectId("5fa91cc7d7d52f1e389dee1e")
 "productId" : ObjectId("5f9aab1c8e475489270ebe2d")

我已尝试将 $or 与 $elemMatch 一起使用,但无法获得所需的结果。我也在考虑使用$cond。谁能帮我构建查询。

【问题讨论】:

    标签: database mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    我们可以做到

    • $facet 帮助对传入的文档进行分类
    • arArray中,我们得到所有有"references.languageCode": "ar"的文档(这个文档可能有也可能没有en),然后解构references数组,然后选择"references.languageCode": "ar" 仅使用 $match$group 帮助获取属于"references.languageCode": "ar" 的所有productId
    • enArray 中,我们获取只有"references.languageCode": "en" 的文档。其他类似arArray
    • $concatArrays 有助于概念化 arArray、enArray 数组
    • $unwind 有助于解构数组。
    • $replaceRoot 有助于使对象进入根目录

    这是 mongo 脚本。

    db.collection.aggregate([
      {
        $facet: {
          arAarray: [
            {
              $match: {
                "references.languageCode": "ar"
              }
            },
            {
              $unwind: "$references"
            },
            {
              $match: {
                "references.languageCode": "ar"
              }
            },
            {
              $group: {
                _id: "$_id",
                productId: {
                  $addToSet: "$references.productId"
                }
              }
            }
          ],
          enArray: [
            {
              $match: {
                $and: [
                  {
                    "references.languageCode": "en"
                  },
                  {
                    "references.languageCode": {
                      $ne: "ar"
                    }
                  }
                ]
              }
            },
            {
              $unwind: "$references"
            },
            {
              $group: {
                _id: "$_id",
                productId: {
                  $addToSet: "$references.productId"
                }
              }
            }
          ]
        }
      },
      {
        $project: {
          combined: {
            "$concatArrays": [
              "$arAarray",
              "$enArray"
            ]
          }
        }
      },
      {
        $unwind: "$combined"
      },
      {
        "$replaceRoot": {
          "newRoot": "$combined"
        }
      }
    ])
    

    工作Mongo playground

    【讨论】:

    • 谢谢,但是当我的产品集合中没有“ar”条目时,它会返回生产 ID 的空数组。相反,我想要我的produceId中的“en”条目。
    • @VishalKumar 你能检查一下这个mongoplayground.net/p/Ui2gldya49P 是否正确。所以我可以回答一下
    • @VishalKumar 我做了一些更改,并更新了脚本。看看
    • @VishalKumar 这对您有帮助吗?
    • 是的,它确实对我有帮助。非常感谢。
    【解决方案2】:

    您可以测试此解决方案,看看它是否对您的问题有用:

    db.collection.aggregate([
        {
            $addFields: {
                foundResults:
                {
                    $cond: {
                        if: { $in: ["ar", "$references.languageCode"] }, then:
                        {
                            $filter: {
                                input: "$references",
                                as: "item",
                                cond: {
                                    $and: [{ $eq: ["$$item.languageCode", 'ar'] },
                                    ]
                                }
                            }
                        }
    
                        , else:
                        {
                            $filter: {
                                input: "$references",
                                as: "item",
                                cond: {
                                    $and: [{ $eq: ["$$item.languageCode", 'en'] },
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        { $unwind: "$foundResults" },
        { $replaceRoot: { newRoot: { $mergeObjects: ["$foundResults"] } } },
        { $project: { _id: 0, "productId": 1 } }
    ])
    

    【讨论】:

      猜你喜欢
      • 2012-08-22
      • 2012-08-26
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多