【问题标题】:Collect distinct field names at nested level with specific condition在具有特定条件的嵌套级别收集不同的字段名称
【发布时间】:2017-07-03 09:31:29
【问题描述】:

我有问题陈述,其中我需要“config.first.second”子级别的所有字段名称,其中包含字段至少一次为真。 这是我的 mongo 集合对象。

   [ {
        "_id" : ObjectId("560e97f4a78eb445cd2d75e5"),
        "config" : {
            "first" : {
                "second" : {
                    "field1" : {
                       "include":"true"
                    },
                    "field3" : {
                      "include":"true"
                    },
                    "field9" : {
                        "include":"false"
                    },
                    "field6" : {
                        "include":"false"
                    }
                }
            }
        },
        "date_created" : "Fri Oct 02 14:43:00 UTC 2015",
        "last_updated" : "Mon Apr 11 15:26:37 UTC 2016",
        "id" : ObjectId("560e97f4a78eb445cd2d75e5")
    },
    {
        "_id" : ObjectId("56154465a78e41c04692af20"),
        "config" : {
            "first" : {
                "second" : {
                    "field1" : {
                        "include":"true"
                    },
                    "field3" : {
                        "include":"false"
                    },
                    "field7" : {
                    "include":"true"
                    }
                }
            }
        },
        "date_created" : "Wed Oct 07 16:12:21 UTC 2015",
        "last_updated" : "Mon Apr 11 15:18:58 UTC 2016",
        "id" : ObjectId("56154465a78e41c04692af20")
    }
]

使用上面的 mongo 集合。查询必须返回结果

["field1","field3","field7"]

【问题讨论】:

  • 这是一个可怕的结构,绝对没有实用程序可供查询。你需要通过 JavaScript 递归来做任何事情。结构需要改变,因为这根本不是您使用数据库的目的。如果您认为这是您想要的结构,请使用 XML 文档存储。
  • 可能是,但无法更改。是不是我只能循环。不像一个好的解决方案。尝试像这样进行投影 db.getCollection('my_collection').aggregate([ { $project : {result: "$config.first.second" } } ]) 但没有帮助
  • 您不能使用聚合或任何标准查询词。仅限 mapReduce。
  • stackoverflow.com/questions/2298870/… 。试过这个但不适合我。也许我错过了什么

标签: javascript mongodb mapreduce mongodb-query aggregation-framework


【解决方案1】:

您可以使用 mapReduce 运行:

db.collection.mapReduce(
  function() {
    Object.keys(this.config.first.second)
      .filter( k => this.config.first.second[k].include === "true" )
      .forEach(k => emit(k,1) );
  },
  function() { },
  { 
    "out": { "inline": 1 },

  }
)['results'].map( d => d._id )

如果你有 MongoDB 3.4 那么你可以使用.aggregate():

db.collection.aggregate([
  { "$project": {
    "field": {
      "$filter": {
        "input": { "$objectToArray": "$config.first.second" },
        "as": "f",
        "cond": { "$eq": [ "$$f.v.include", "true" ] }
      }
    }
  }},
  { "$unwind": "$field" },
  { "$group": { "_id": "$field.k" } }
]).toArray().map(d => d._id)

返回:

[
    "field1",
    "field3",
    "field7"
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2016-06-21
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多