MongoDB查询:列出具有Value NaN的所有字段

时间:2018-04-11 07:53:57

标签: mongodb mongodb-query aggregation-framework nan

假设MongoDB有一个带有“sample1”对象的集合,该对象包含以下字段:

/* 1 */ {
    "_id" : 123456,
    "name" : "question",
    "day" : "2018-03-21",
    "field1" : 10,
    "field2" : NaN,
    "field3" : NaN,
    "field4" : NaN,
    "field5" : NaN }

/* 2 */ {
    "_id" : 7896321,
    "name" : "question",
    "day" : "2018-03-22",
    "field1" : NaN,
    "field2" : NaN,
    "field3" : NaN,
    "field4" : NaN,
    "field5" : 20 }

我想要的是一个字段“列表”,它只显示那些没有NaN作为值的字段。 查询可能看起来像

db.getCollection('sample1').find({"*" : $ne{NaN}})

[注意:我找到的所有答案都指定了fieldname(s)= Key。唉,我需要一个通配符而不是名称]

上述demo_query的结果类似于

Result:
/* 1 */
{
    "_id" : 123456,
    "name" : "question",
    "day" : "2018-03-21",
    "field1" : 10
}
/* 2 */
{
    "_id" : 7896321,
    "name" : "question",
    "day" : "2018-03-22",
    "field5" : 20
}

随后提出了一个跟进问题: 是否有可能修改上述查询,即获得 (A)一个具有NaN或NaN值的字段列表 (B)没有NaN的一个字段列表?

Result (A): List of fields that have at least in one object a given field might have NaN 
    {"field1"
    "field2" 
    "field3"
    "field4" 
    "field5" }

Result (B): List of fields that never (= in no object of a given collection) have the value NaN 
    {"_id"
    "name"
    "day" }

我在JS方面的经验非常有限。可能这可以使用PyMongo完成吗?

万分感谢任何建议!

1 个答案:

答案 0 :(得分:1)

利用聚合框架中提供的 $objectToArray 运算符来转换顶级文档(通过系统变量 $$ROOT )成为键值对的数组,即保存字段名称的键,值保存字段值。这可以通过表达式

来完成
{ "$objectToArray": "$$ROOT" }

将返回,例如带有_id的第一个文档:123456

[ 
    {
        "k" : "_id",
        "v" : 123456
    }, 
    {
        "k" : "name",
        "v" : "question"
    }, 
    {
        "k" : "day",
        "v" : "2018-03-21"
    }, 
    {
        "k" : "field1",
        "v" : 10
    }, 
    {
        "k" : "field2",
        "v" : NaN
    }, 
    {
        "k" : "field3",
        "v" : NaN
    }, 
    {
        "k" : "field4",
        "v" : NaN
    }, 
    {
        "k" : "field5",
        "v" : NaN
    }
]

获取此数组后,您可以使用 $filter $map 进行一些过滤,然后获取所需的列表。

以下聚合操作

db.getCollection('sample1').aggregate([
    { "$addFields": { 
        "NaNFields": {
            "$map": {
                "input": {
                    "$filter": {
                        "input": { "$objectToArray": "$$ROOT" },
                        "as": "el",
                        "cond": { "$eq": [ "$$el.v", NaN ] }
                    }
                },
                "as": "field",
                "in": "$$field.k"
            }
        },
        "NonNaNFields": {
            "$map": {
                "input": {
                    "$filter": {
                        "input": { "$objectToArray": "$$ROOT" },
                        "as": "el",
                        "cond": { "$ne": [ "$$el.v", NaN ] }
                    }
                },
                "as": "field",
                "in": "$$field.k"
            }
        } 
    } }
])

产量

/* 1 */
{
    "_id" : 123456,
    "name" : "question",
    "day" : "2018-03-21",
    "field1" : 10,
    "field2" : NaN,
    "field3" : NaN,
    "field4" : NaN,
    "field5" : NaN,
    "NaNFields" : [ 
        "field2", 
        "field3", 
        "field4", 
        "field5"
    ],
    "NonNaNFields" : [ 
        "_id", 
        "name", 
        "day", 
        "field1"
    ]
}

/* 2 */
{
    "_id" : 7896321,
    "name" : "question",
    "day" : "2018-03-22",
    "field1" : NaN,
    "field2" : NaN,
    "field3" : NaN,
    "field4" : NaN,
    "field5" : 20,
    "NaNFields" : [ 
        "field1", 
        "field2", 
        "field3", 
        "field4"
    ],
    "NonNaNFields" : [ 
        "_id", 
        "name", 
        "day", 
        "field5"
    ]
}