简体   繁体   English

按数组字段的元素索引顺序查找 mongodb 集合中的文档

[英]Finding documents in mongodb collection by order of elements index of array field

Array field in collection:集合中的数组字段:

"fruits": [                    "fruits": [                    "fruits": [
    {"fruit1": "banana"},          {"fruit2": "apple"},           {"fruit3": "pear"},
    {"fruit2": "apple"},           {"fruit4": "orange"},          {"fruit2": "apple"}, 
    {"fruit3": "pear"},            {"fruit1": "banana"},          {"fruit4": "orange"},
    {"fruit4": "orange"}           {"fruit3": "pear"}             {"fruit1": "banana"} 
]

I need to find those documents in collections, where "banana" signed before "apple".我需要在 collections 中找到那些文件,其中“banana”在“apple”之前签名。 Does mongodb allows to compare elements in array just like: mongodb 是否允许像这样比较数组中的元素:

if (fruits.indexOf('banana') < fruits.indexOf('apple')) return true;

Or maybe there is any other method to get result i need?或者也许还有其他方法可以获得我需要的结果?

MongoDB's array query operations do not support any positional search as you want. MongoDB 的数组查询操作不支持您想要的任何位置搜索。

You can, however, write a $where query to do what you want:但是,您可以编写一个$where查询来执行您想要的操作:

db.yourCollection.find({
  $where: function() { 
    return (this.fruits.indexOf('banana') < this.fruits.indexOf('apple')) 
  }
})

Be advised though, you won't be able to use indexes here and the performance will be a problem.不过请注意,您将无法在此处使用索引,并且性能会成为问题。

Another approach you can take is to rethink the database design, if you can specify what it is you're trying to build, someone can give you specific advise.您可以采取的另一种方法是重新考虑数据库设计,如果您可以指定要构建的内容,有人可以给您具体的建议。

One more approach: pre-calculate the boolean value before persisting to DB as a field and query on true / false.另一种方法:在将 boolean 值作为字段持久化到 DB 并查询 true / false 之前预先计算。

Consider refactoring your schema if possible.如果可能,请考虑重构您的模式。 The dynamic field names(ie fruit1, fruit2...) make it unnecessarily complicated to construct a query.动态字段名称(即 fruit1、fruit2...)使构造查询变得不必要地复杂。 Also, if you require frequent queries by array index, you should probably store your array entries in individual documents with some sort keys to facilitate sorting with index.此外,如果您需要通过数组索引进行频繁查询,您可能应该将数组条目存储在带有一些排序键的单个文档中,以便于使用索引进行排序。

Nevertheless, it is achievable through $unwind and $group the documents again.然而,它可以通过$unwind$group文件再次实现。 With includeArrayIndex clause, you can get the index inside array.使用includeArrayIndex子句,您可以获得数组内的索引。

db.collection.aggregate([
  {
    "$unwind": {
      path: "$fruits",
      includeArrayIndex: "idx"
    }
  },
  {
    "$addFields": {
      fruits: {
        "$objectToArray": "$fruits"
      }
    }
  },
  {
    "$addFields": {
      "bananaIdx": {
        "$cond": {
          "if": {
            $eq: [
              "banana",
              {
                $first: "$fruits.v"
              }
            ]
          },
          "then": "$idx",
          "else": "$$REMOVE"
        }
      },
      "appleIdx": {
        "$cond": {
          "if": {
            $eq: [
              "apple",
              {
                $first: "$fruits.v"
              }
            ]
          },
          "then": "$idx",
          "else": "$$REMOVE"
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      fruits: {
        $push: {
          "$arrayToObject": "$fruits"
        }
      },
      bananaIdx: {
        $max: "$bananaIdx"
      },
      appleIdx: {
        $max: "$appleIdx"
      }
    }
  },
  {
    $match: {
      $expr: {
        $lt: [
          "$bananaIdx",
          "$appleIdx"
        ]
      }
    }
  },
  {
    $unset: [
      "bananaIdx",
      "appleIdx"
    ]
  }
])

Mongo Playground蒙戈游乐场

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

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