【问题标题】:Mongoose Get field with conditionMongoose 获取有条件的字段
【发布时间】:2021-12-22 11:19:48
【问题描述】:

我有这样的架构:

parentId: Number
name:[ 
       new Schema({
           language: { type: String, enum: ['en-US', 'fr-CA'] },
           text: String,
       },{ _id: false }
       );
     ],
isActive: Boolean
...

以及如下示例数据:

{
  parentId:1,
  "name": [
            {"language": "en-US", "text": "Book"},
            {"language": "fr-CA", "text": "livre"}
          ],
   isActive:true
   // and so many other fields
},
{
  parentId:1,
  "name": [
            {"language": "en-US", "text": "Pen"}
          ],
   isActive:true
   // and so many other fields
}

我的猫鼬正在搜索法语文本:

db.langs.find({
  "name.language":"fr-CA", parentId: 1
})

第一季度。我怎样才能像这样用法语返回名称:

{
  parentId:1,
  "name": "livre",
   isActive:true
   // and so many other fields
}

第二季度。猫鼬有没有可能我可以返回法语文本,如果法语不存在,它会返回英语?

{
  parentId:1,
  "name": "livre",
   isActive:true
   // and so many other fields
},
{
  parentId:1,
  "name": "pen",
   isActive:true
   // and so many other fields
}

【问题讨论】:

    标签: javascript node.js mongodb mongoose aggregation-framework


    【解决方案1】:

    问题一:

    您可以使用$unwind 解构数组,并使用$match 像一个对象。至少$addFields 用所需的值覆盖name 字段(如果有多个字段比使用$project 更好)。所有这些都在这样的聚合管道中:

    db.collection.aggregate([
      {
        "$match": {
          "parentId": 1
        }
      },
      {
        "$unwind": "$name"
      },
      {
        "$match": {
          "name.language": "fr-CA"
        }
      },
      {
        "$addFields": {
          "name": "$name.text"
        }
      }
    ])
    

    例如here

    问题 2:

    您可以使用$facet 来创建“两种方式”。如果存在法语结果,则一个,如果不存在,则另一个。然后检查是否存在以像这样输出一个或另一个值:

    db.collection.aggregate([
      {
        "$match": {
          "parentId": 1
        }
      },
      {
        "$unwind": "$name"
      },
      {
        "$facet": {
          "french": [
            {
              "$match": {
                "name.language": "fr-CA"
              }
            }
          ],
          "notFrench": [
            {
              "$match": {
                "name.language": "en-US"
              }
            }
          ]
        }
      },
      {
        "$project": {
          "result": {
            "$cond": {
              "if": {
                "$eq": [
                  {
                    "$size": "$french"
                  },
                  0
                ]
              },
              "then": "$notFrench",
              "else": "$french"
            }
          }
        }
      }
    ])
    

    例如here

    【讨论】:

    【解决方案2】:

    你也可以通过数组操作来做到这一点。

    查询1

    • 匹配父级 1
    • fitler 只保留法语,并使用text
    • 匹配到有名字(删除没有法语书的文档)

    Test code here

    aggregate(
    [{"$match": {"parentId": {"$eq": 1}}},
      {"$set": 
        {"name": 
          {"$getField": 
            {"field": "text",
              "input": 
              {"$arrayElemAt": 
                [{"$filter": 
                    {"input": "$name",
                      "cond": {"$eq": ["$$this.language", "fr-CA"]}}},
                  0]}}}}},
      {"$match": {"$expr": {"$eq": [{"$type": "$name"}, "string"]}}}])
    

    查询2

    • 匹配父级 1
    • 减少
      • 如果值(我之前找到)法语我保留它
      • 如果当前是法国,我保留这个
      • 否则,如果当前是我们,我保留这个
      • 其他值(保持初始值为空{})
    • 匹配到有一个名字(删除没有法语或美国书的文档)

    Test code here

    aggregate(
    [{"$match": {"parentId": {"$eq": 1}}},
      {"$set": 
        {"name": 
          {"$getField": 
            {"field": "text",
              "input": 
              {"$reduce": 
                {"input": "$name",
                  "initialValue": {},
                  "in": 
                  {"$switch": 
                    {"branches": 
                      [{"case": {"$eq": ["$$value.language", "fr-CA"]},
                          "then": "$$value"},
                        {"case": {"$eq": ["$$this.language", "fr-CA"]},
                          "then": "$$this"},
                        {"case": {"$eq": ["$$this.language", "en-US"]},
                          "then": "$$this"}],
                      "default": "$$value"}}}}}}}},
      {"$match": {"$expr": {"$eq": [{"$type": "$name"}, "string"]}}}])
    

    【讨论】:

    猜你喜欢
    • 2016-09-03
    • 2018-04-27
    • 1970-01-01
    • 2019-08-17
    • 2021-03-24
    • 1970-01-01
    • 2015-10-16
    • 2019-12-06
    • 2023-03-17
    相关资源
    最近更新 更多