0

我正在使用动态表单构建器将值存储到 mongo 中。这意味着这些字段是在运行时定义的。

现在我试图让用户构建一个动态的数据网格视图,以便他们可以一目了然地选择他们想要查看的字段。因此,我需要投影存储在集合项中的字段子集。

这是集合中 2 条记录的示例

{
"_id": {
    "$oid": "511ff0a8521e66d41b0d35d6"
},
"FormID": {
    "$uuid": "413ba627-94bf-0ca7-49b3-9ca2a1a3e9b5"
},
"ResultID": {
    "$uuid": "45f455ae-8486-aaa9-b97a-e480bfdf3db4"
},
"FieldValues": [
    {
        "FieldID": "first name",
        "FieldValue": "John"
    },
    {
        "FieldID": "last name",
        "FieldValue": "smith"
    },
    {
        "FieldID": "school",
        "FieldValue": "high school"
    },
    {
        "FieldID": "favorite subject",
        "FieldValue": "math"
    },

]
},

{
"_id": {
    "$oid": "511ff0a8521e66d41b0d35d7"
},
"FormID": {
    "$uuid": "413ba627-94bf-0ca7-49b3-9ca2a1a3e9b5"
},
"ResultID": {
    "$uuid": "45f455ae-8486-aaa9-b97a-e480bfdf3db5"
},
"FieldValues": [
    {
        "FieldID": "first name",
        "FieldValue": "sarah"
    },
    {
        "FieldID": "last name",
        "FieldValue": "smith"
    },
    {
        "FieldID": "school",
        "FieldValue": "high school"
    },
    {
        "FieldID": "favorite subject",
        "FieldValue": "english"
    },

]
},

假设我想投影结果 ID、名字、姓氏

在 SQL 中——我会在自己的表中定义 FieldValues,并且我会对 ResultId =(父结果 id)和 FieldID =“名字”的字段值进行子查询,然后对“姓氏”进行另一个子查询"等等以使结果变平。

我一直在试图弄清楚如何用 mongo 做到这一点。我能够找到 $slice 运算符,但这只能让您获得一组连续的数组元素。

我不想获取整个文档的原因是,在某些情况下,我的客户已经定义了 400 多个要跟踪的字段。即使在 200 行上反序列化所有这些也可能意味着 100MB 的数据通过网络传递并反序列化(慢)。

任何意见/建议将不胜感激

4

1 回答 1

2

您可以构建适当的聚合框架语法来准确返回您想要的内容。它可能不够快,但它会返回您想要的确切格式,而无需拉下整个文档。为了让它更快,我假设您可以避免在整个集合中运行它,方法是让管道的第一阶段{$match}只选择相关的文档子集(并且应该索引该标准)。

在您的两个示例文档的字段上使用以下管道阶段,您first name只能last name返回 _id 和这些字段。对于一组给定的字段 ID,您可以通过编程方式生成此管道。

unwind = { "$unwind" : "$FieldValues" };

match = { "$match" : {
        "FieldValues.FieldID" : {
            "$in" : [
                "first name",
                "last name"
            ]
        }
    }
};

proj = { "$project" : {
        "first name" : {
            "$cond" : [
                {
                    "$eq" : [
                        "first name",
                        "$FieldValues.FieldID"
                    ]
                },
                "$FieldValues.FieldValue",
                "  skip"
            ]
        },
        "last name" : {
            "$cond" : [
                {
                    "$eq" : [
                        "last name",
                        "$FieldValues.FieldID"
                    ]
                },
                "$FieldValues.FieldValue",
                "  skip"
            ]
        }
    }
};

group = { "$group" : {
        "_id" : "$_id",
        "first name" : {
            "$max" : "$first name"
        },
        "last name" : {
            "$max" : "$last name"
        }
    }
};

db.project.aggregate(unwind, match, proj, group)
{
    "result" : [
        {
            "_id" : ObjectId("511ff0a8521e66d41b0d35d7"),
            "first name" : "sarah",
            "last name" : "smith"
        },
        {
            "_id" : ObjectId("511ff0a8521e66d41b0d35d6"),
            "first name" : "John",
            "last name" : "smith"
        }
    ],
    "ok" : 1
}
于 2013-04-21T13:52:59.983 回答