简体   繁体   English

Mongoose 获取带条件的字段

[英]Mongoose Get field with condition

I have a schema like this:我有一个这样的架构:

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

and sample data like the following:和示例数据如下:

{
  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
}

my mongoose searching for French texts:我的猫鼬搜索法语文本:

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

Q1.一季度。 How can I return the name in French like this:我怎样才能像这样用法语返回名字:

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

Q2. Q2。 Is there any possibility in mongoose that I can return the french text and if the french is not there, it returns English?猫鼬有没有可能返回法语文本,如果法语不在那里,它会返回英语?

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

Question 1:问题 1:

You can use $unwind to deconstruct the array and $match like an object.您可以像对象一样使用$unwind来解构数组和$match And least do $addFields to overwrite name field with the desired value (if there are multiple fields is better options than use $project ).并且至少做$addFields用所需的值覆盖name字段(如果有多个字段是比使用$project更好的选择)。 All this in an aggregation pipeline like this:所有这些都在这样的聚合管道中:

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

Example here示例在这里

Question 2:问题2:

You can use $facet to create "two ways".您可以使用$facet来创建“两种方式”。 One if exists french result and another if not exists.一个如果存在法国结果,另一个如果不存在。 And then check if exists to output one value or another like this:然后检查是否存在以输出一个或另一个值,如下所示:

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"
        }
      }
    }
  }
])

Example here示例在这里

You can do it with array operations also.你也可以用数组操作来做到这一点。

Query1查询1

  • match parent 1匹配父项 1
  • fitler to keep only french, and take the text fitler 只保留法语,并取text
  • match to have a name (to remove documents that didn't had a french book)匹配名称(删除没有法语书籍的文档)

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"]}}}])

Query2查询2

  • match parent 1匹配父项 1
  • reduce降低
    • if value(i found it before) french i keep it如果值(我之前找到它)法语我保留它
    • else if the current is france i keep this否则如果当前是法国我保留这个
    • else if the current is us i keep this否则如果当前是我们我保留这个
    • else value (keep the initial value that is empty {}) else 值(保留为空的初始值 {})
  • match to have a name (to remove documents that didn't had a french or us book)匹配名称(删除没有法语或美国书籍的文件)

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"]}}}])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM