Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 有条件地投影匹配数组项_Arrays_Mongodb_Mongodb Query_Aggregation Framework - Fatal编程技术网

Arrays 有条件地投影匹配数组项

Arrays 有条件地投影匹配数组项,arrays,mongodb,mongodb-query,aggregation-framework,Arrays,Mongodb,Mongodb Query,Aggregation Framework,我有一个名为questions的集合,其中包含以下文档: { "formats": [ { "language_id": 1, "text": "question text1" }, { "language_id": 2, "text": "question text 2" } ], "qid": "HQSRFA3

我有一个名为
questions
的集合,其中包含以下文档:

{
    "formats": [
        {
            "language_id": 1,
            "text": "question text1"
        },
        {
            "language_id": 2,
            "text": "question text 2"
        }
    ],
    "qid": "HQSRFA3T"
}
db.questions.aggregate([ { $match: {'qid': 'HQSRFA3T'}}, { $project: {
  formats: {
    $filter: {
      input: '$formats',
      as: 'format',
      cond: {
        $or: [
          { $eq: ['$$format.language_id', 1] },
          { $eq: ['$$format.language_id', 3] }
        ]
      }
    }
  },
  _id: 0
}}])
我想编写一个查询,如果特定的
language\u id
不存在,那么默认情况下应该返回带有1的
language\u id

到目前为止,我尝试了两个查询:

db.questions.aggregate([
  { 
    $match: {
      'qid': 'HQSRFA3T'
    }
  },
  {
    $project: {
      formats: {
        $ifNull: [
          { $filter: { input: '$formats', as: 'format', cond: {$eq: ['$$format.language_id', 3]}} },
          { $filter: { input: '$formats', as: 'format', cond: {$eq: ['$$format.language_id', 1]}} }
        ]
      },
      _id: 0
    }
  }
])
此查询的结果如下所示:

{
    "formats": [
        {
            "language_id": 1,
            "text": "question text1"
        },
        {
            "language_id": 2,
            "text": "question text 2"
        }
    ],
    "qid": "HQSRFA3T"
}
db.questions.aggregate([ { $match: {'qid': 'HQSRFA3T'}}, { $project: {
  formats: {
    $filter: {
      input: '$formats',
      as: 'format',
      cond: {
        $or: [
          { $eq: ['$$format.language_id', 1] },
          { $eq: ['$$format.language_id', 3] }
        ]
      }
    }
  },
  _id: 0
}}])
{“格式”:[]}

然后还有另一个类似这样的查询:

{
    "formats": [
        {
            "language_id": 1,
            "text": "question text1"
        },
        {
            "language_id": 2,
            "text": "question text 2"
        }
    ],
    "qid": "HQSRFA3T"
}
db.questions.aggregate([ { $match: {'qid': 'HQSRFA3T'}}, { $project: {
  formats: {
    $filter: {
      input: '$formats',
      as: 'format',
      cond: {
        $or: [
          { $eq: ['$$format.language_id', 1] },
          { $eq: ['$$format.language_id', 3] }
        ]
      }
    }
  },
  _id: 0
}}])
如果数组中同时存在
语言id
,此查询将返回两个元素。

有几种方法:

理想情况下,您可以使用MongoDB 3.4,然后将其与以下内容结合使用:

如果您真正想要的是匹配的
“text”
,则需要稍加修改:

db.questions.aggregate([
  { "$match": { "qid": "HQSRFA3T" } },
  { "$project": {
    "text": {
      "$cond": {
        "if": { "$in": [ 3, "$formats.language_id"] },
        "then": { 
          "$arrayElemAt": [
            "$formats.text",
            { "$indexOfArray": [ "$formats.language_id", 3 ] }
          ]
        },
        "else": {
          "$arrayElemAt": [
            "$formats.text",
            { "$indexOfArray": [ "$formats.language_id", 1 ] }
          ]
        }
      }
    }}
  }
])
这是因为如果返回指示“未找到”的
-1
,则会相应地进行分支:

或者,与以下内容一起使用:

如果您至少有MongoDB 3.2,您甚至可以在最后一个表单上更改,只返回位置
0
处的“单个”匹配数组元素

db.questions.aggregate([
  { "$match": { "qid": "HQSRFA3T" } },
  { "$project": {
    "formats": {
      "$cond": {
        "if": { "$gt": [
          { "$size": { 
            "$filter": { 
              "input": "$formats",
               "cond": { "$eq": [ "$$this.language_id", 3 ] }
            }
          }},
          0
        ]},
        "then": {
          "$arrayElemAt": [
            { "$filter": {
              "input": "$formats",
              "cond": { "$eq": [ "$$this.language_id", 3 ] }
            }},
            0
          ]
        },
        "else": {
          "$arrayElemAt": [
            { "$filter": {
              "input": "$formats",
              "cond": { "$eq": [ "$$this.language_id", 1 ] }
            }},
            0
          ]
        }
      }
    }
  }}
])
如果使用了
条件的
上的其他选项,以匹配数组元素上的比较:

"if": { "$in": [ 3, "$formats.language_id" ] }
但由于这需要MongoDB 3.4,因此您也可以使用操作符

尝试“强制”多个匹配,然后最终放弃其中一个,这没有什么意义,但您可以通过以下方式“实现”:


所以它就在那里,但这只是额外的工作,几乎没有什么收益,因为在最好的情况下,条件与“默认”情况匹配,并且您仍然需要“过滤掉”仅为“首选”情况无论如何都要匹配。

第一个查询将返回错误的结果,
$indexOfArray
返回-1,
$arrayElemAt
根据文档给出数组中的最后一个元素。@RahulSharma Argh!当然,您的权限
$ifNull
可能不是最好的选择。我想编写一个查询,返回到使用第三个查询正确实现的
语言id
1。我刚刚指出,如果$indexOfArray返回-1,$arrayElemAt不会返回null。无论如何,感谢您对第三个查询的帮助。@RahulSharma我还是修改了第一个查询
$ifNull
不起作用,因为没有返回
null
,因此
$cond
在所有情况下都有效。