Mongo DB聚合管道:将字符串转换为文档/对象

时间:2020-06-05 07:26:43

标签: mongodb aggregation-framework

具有“ String”类型的字段,其中包含对象/文档的表示形式

" {"a":35,b:[1,2,3,4]}"

我知道这是一个奇怪的构造,但我无法更改。 我的目标是提取“ a”的值。 由于字符串表示的文档被嵌套并重复,因此正则表达式不适合。 那么,如何在mongo db聚合中/将这个String转换为对象,以便可以在接下来的聚合步骤中对其进行处理? (可以使用python提取字符串来生成字典并提取信息,但我想保留在聚合管道中,因此具有更好的性能)

3 个答案:

答案 0 :(得分:1)

在 4.4 中这有效

db.target.aggregate([{$project: { 
                         X: "$AD_GRAPHIC",
                         Y : {
                           $function : {
                               body: function(jsonString) {
                                 return JSON.parse(jsonString)
                               },
                               args: [ "$AD_GRAPHIC"],
                               lang: "js"
                           }
                         }
                     }
                    }])

基本上使用 $function 运算符来调用 JSON 解析器。 (假设您已启用 Javascript)

结果

{ "_id" : ObjectId("60093dc8f2c829000e38a8d0"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"modem.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "modem.jpg" } }
{ "_id" : ObjectId("60093dc8f2c829000e38a8d1"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"monitor.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "monitor.jpg" } }
{ "_id" : ObjectId("60093dc8f2c829000e38a8d2"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"mousepad.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "mousepad.jpg" } }
{ "_id" : ObjectId("60093dc8f2c829000e38a8d3"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"keyboard.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "keyboard.jpg" } }
>

答案 1 :(得分:0)

您可以只使用JSON.parse()

例如

db.getCollection('system').find({
    a: JSON.parse('{"a":35,b:[1,2,3,4]}').a
})

答案 2 :(得分:0)

MongoDB引擎中没有原生方法来解析字段中的JSON斑点。但是,我建议您以您选择的语言在客户端进行操作,然后在需要时将其保存回去。

或者,如果您的数据太大而仍然需要聚合,则可以使用regex并从JSON中投影出必填字段,然后再使用它们进行过滤等...

例如,如果我们插入以下文档:

> db.test.insertOne({ name: 'test', blob: '{"a":35,b:[1,2,3,4]}' })
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5ed9fe21b5d91941c9e85cdb")
}

然后我们可以使用一些正则表达式来投影数组:

db.test.aggregate([
   { $addFields: { b: { $regexFind: { input: "$blob", regex: /\[(((\d+,*))+)\]/ }  } } },
   { $addFields: { b: { $split: [ { $arrayElemAt: [ "$b.captures", 0 ] }, "," ] } } }
]);

{
        "_id" : ObjectId("5ed9fe21b5d91941c9e85cdb"),
        "name" : "test",
        "blob" : "{\"a\":35,b:[1,2,3,4]}",
        "b" : [
                "1",
                "2",
                "3",
                "4"
        ]
}

这意味着我们可以进行一些过滤,排序和其他任何聚合阶段。