【问题标题】:Is there a way to project the type of a field有没有办法投影字段的类型
【发布时间】:2014-03-10 03:24:53
【问题描述】:

假设我们有类似以下文档的内容,但我们只想返回包含数字信息的字段:

{
    "_id" : ObjectId("52fac254f40ff600c10e56d4"),
    "name" : "Mikey",
    "list" : [ 1, 2, 3, 4, 5 ],
    "people" : [ "Fred", "Barney", "Wilma", "Betty" ],
    "status" : false,
    "created" : ISODate("2014-02-12T00:37:40.534Z"),
    "views" : 5
}

现在我知道我们可以使用$type 运算符来查询匹配特定类型的字段。但是我还没有偶然发现将 $project 作为字段值的方法。因此,如果我们查看“展开”形式的文档,您会看到:

{
    "_id" : ObjectId("52fac254f40ff600c10e56d4"),
    "name" : 2,
    "list" : 16,
    "people" : 2
    "status" : 8,
    "created" : 9,
    "views" : 16
}

最终目标是仅列出匹配某种类型的字段,比方说比较以获取数字类型并过滤掉字段,经过多次文档修改,产生如下结果:

{
    "_id" : ObjectId("52fac254f40ff600c10e56d4"),
    "list" : [ 1, 2, 3, 4, 5 ],
    "views" : 5
}

有没有人有办法处理这个问题。

【问题讨论】:

    标签: mongodb mapreduce mongodb-query aggregation-framework


    【解决方案1】:

    有几个问题使这不切实际:

    1. 由于查询是进行投影的能力的一个独特参数,因此仅通过单个查询是不可能的,因为投影不会受到查询结果的影响
    2. 由于聚合框架无法迭代字段和检查类型,这也不是一个选项

    话虽如此,使用 Map-Reduce 的方式有点古怪,它确实得到了类似的答案,尽管在 Map-Reduce 样式的输出中并不出色:

    map = function() {
        function isNumber(n) {
          return !isNaN(parseFloat(n)) && isFinite(n);
        }
    
        var numerics = [];
        for(var fn in this) {
            if (isNumber(this[fn])) {
                numerics.push({f: fn, v: this[fn]});
            }
            if (Array.isArray(this[fn])) {
                // example ... more complex logic needed
                if(isNumber(this[fn][0])) {
                    numerics.push({f: fn, v: this[fn]});
                }
            }
        }
        emit(this._id, { n: numerics });
    };
    
    reduce = function(key, values) {
      return values;  
    };
    

    虽然不完整,但结果和你想要的差不多:

    "_id" : ObjectId("52fac254f40ff600c10e56d4"),
     "value" : {
             "n" : [
                     {
                             "f" : "list",
                             "v" : [
                                     1,
                                     2,
                                     3,
                                     4,
                                     5
                             ]
                     },
                     {
                             "f" : "views",
                             "v" : 5
                     }
             ]
     }
    

    地图只是查看每个属性并决定它是否看起来像一个数字......如果是这样,添加到一个将作为对象存储的数组中,这样 map-reduce 引擎就不会阻塞数组输出。我在示例代码中保持简单——您可以肯定地改进数字和数组检查的逻辑。 :)

    当然,它不像 find 或聚合那样实时,但由于 MongoDB 在设计时没有考虑到这一点,如果你真的想要这个功能,这可能必须这样做。

    【讨论】:

    • 是的。这也是我的想法。这来自另一个基本上想以这种方式过滤字段的问题。也许聚合中的 $type 运算符会很好,很像日期运算符,但我真的不确定这种东西的广泛用途。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    相关资源
    最近更新 更多