MongoDB动态条件过滤

发布于 2025-01-14 13:53:24 字数 4197 浏览 0 评论 0原文

我正在尝试创建一个表单生成器和生成器,并从生成的表单中收集答案。收集答案后,我想根据一些过滤参数对它们进行过滤,并获得每个类别的平均结果。

问题已绑定类别(attributeGroupOne&Two)。

我的答案有以下结构。

{
    "form": [{
        "_id": {
            "$oid": "62295d028b6b895048b7da96"
        },
        "questionType": "lickert5",
        "label": "deneme sorusu 1",
        "attributeGroupTwo": "deneme kategorisi alt 2",
        "attributeGroupOne": "deneme kategorisi",
        "name": "Question_1",
        "weight": 4,
        "type": "radio",
        "options": {
            "1": "Çok Az",
            "2": "Az",
            "3": "Bazen",
            "4": "Genellikle",
            "5": "Her Zaman"
        }
    }, {
        "_id": {
            "$oid": "62295d028b6b895048b7da95"
        },
        "questionType": "lickert10",
        "label": "deneme sorusu 2",
        "attributeGroupTwo": "deneme alt 3",
        "attributeGroupOne": "deneme kategorisi",
        "name": "Question_2",
        "weight": 4,
        "type": "radio",
        "options": {
            "1": "1",
            "2": "2",
            "3": "3",
            "4": "4",
            "5": "5",
            "6": "6",
            "7": "7",
            "8": "8",
            "9": "9",
            "10": "10"
        }
    }, {
        "_id": {
            "$oid": "62295d028b6b895048b7da94"
        },
        "questionType": "trueFalse",
        "label": "deneme sorusu 3",
        "attributeGroupTwo": "deneme alt 5",
        "attributeGroupOne": "deneme kategorisi",
        "name": "Question_3",
        "weight": 4,
        "type": "radio",
        "options": {
            "0": "Yanlış",
            "10": "Doğru"
        }
    }, {
        "_id": {
            "$oid": "62295d028b6b895048b7da93"
        },
        "questionType": "lickert5",
        "label": "deneme sorusu 4",
        "attributeGroupTwo": "deneme main sub",
        "attributeGroupOne": "deneme main 2",
        "name": "Question_4",
        "weight": 4,
        "type": "radio",
        "options": {
            "1": "Çok Az",
            "2": "Az",
            "3": "Bazen",
            "4": "Genellikle",
            "5": "Her Zaman"
        }
    }],
    "surveyName": "deneme formu",
    "createdBy": {
        "$oid": "61becc2c230fc12274683b6a"
    },
    "createdAt": {
        "$date": "2022-03-10T02:05:54.039Z"
    },
    "updatedAt": {
        "$date": "2022-03-10T02:05:54.039Z"
    },
    "__v": 0
}

https://i.sstatic.net/xT2Cq.png

无需额外过滤器,仅按过滤类别通过以下查询,我得到了我想要的报告。

      .aggregate([
        { $unwind: '$answers' },
        {
          $group: {
            _id: '$answers.SubCategory',
            CalculatedWeight: { $avg: '$answers.CalculatedWeight' },
            formId: { $first: formId }
          }
        },
        { $project: { _id: 1, CalculatedWeight: 1, formId: 1 } },
        { $out: 'results' }
      ])

结果:

{
    "CalculatedWeight": 19.35483870967742,
    "formId": {
        "$oid": "62295d028b6b895048b7da92"
    }
}

https://i.sstatic.net/HxqBe.png

我成功添加了年龄过滤与以下块

const docs = await model
      .aggregate([
        {
          $match: {
            $and: [
              { age: { $gt: minAge, $lt: maxAge } },
              { formId: { $eq: formId } }
            ]
          }
        },
        { $unwind: '$answers' },
        {
          $group: {
            _id: '$answers.SubCategory',
            CalculatedWeight: { $avg: '$answers.CalculatedWeight' },
            formId: { $first: formId }
          }
        },
        { $project: { _id: 1, CalculatedWeight: 1, formId: 1 } },
        { $out: 'results' }
      ])

但我有 5 个过滤器,分别是性别、部门、年龄、工作年限和教育水平。如果可能的话,我希望能够将它们与动态查询结合起来,但我不想编写 120 个 if 案例来组合它们。我想不出一种以编程方式根据过滤器进行过滤和计算的方法。

先感谢您。问题本身可能不太清楚,抱歉。如果您指出不足之处,我可以详细说明。

编辑: 过滤器类型如下所示。年龄和工作年限将是一个具有最小值和最大值的时期。如果可能的话,我希望能够组合所有过滤器类型,但由于条目池很小~200,这可能在统计上不合理。最常见的过滤器组合是:性别-部门-年龄、工作年限-部门、教育-性别。

过滤器: 性别:字符串 - 枚举 部门:字符串 - 枚举 年龄:数字 - 最小和最大 工作年限:数字 - 最小和最大 教育:字符串 - 枚举

I am trying to create a form builder and generator and from generated forms, I will collect answers. After collecting answers I want to filter them according to some filter parameters and get average results for each category.

Questions have categories(attributeGroupOne&Two) bind to them.

I have the following structure for my answers.

{
    "form": [{
        "_id": {
            "$oid": "62295d028b6b895048b7da96"
        },
        "questionType": "lickert5",
        "label": "deneme sorusu 1",
        "attributeGroupTwo": "deneme kategorisi alt 2",
        "attributeGroupOne": "deneme kategorisi",
        "name": "Question_1",
        "weight": 4,
        "type": "radio",
        "options": {
            "1": "Çok Az",
            "2": "Az",
            "3": "Bazen",
            "4": "Genellikle",
            "5": "Her Zaman"
        }
    }, {
        "_id": {
            "$oid": "62295d028b6b895048b7da95"
        },
        "questionType": "lickert10",
        "label": "deneme sorusu 2",
        "attributeGroupTwo": "deneme alt 3",
        "attributeGroupOne": "deneme kategorisi",
        "name": "Question_2",
        "weight": 4,
        "type": "radio",
        "options": {
            "1": "1",
            "2": "2",
            "3": "3",
            "4": "4",
            "5": "5",
            "6": "6",
            "7": "7",
            "8": "8",
            "9": "9",
            "10": "10"
        }
    }, {
        "_id": {
            "$oid": "62295d028b6b895048b7da94"
        },
        "questionType": "trueFalse",
        "label": "deneme sorusu 3",
        "attributeGroupTwo": "deneme alt 5",
        "attributeGroupOne": "deneme kategorisi",
        "name": "Question_3",
        "weight": 4,
        "type": "radio",
        "options": {
            "0": "Yanlış",
            "10": "Doğru"
        }
    }, {
        "_id": {
            "$oid": "62295d028b6b895048b7da93"
        },
        "questionType": "lickert5",
        "label": "deneme sorusu 4",
        "attributeGroupTwo": "deneme main sub",
        "attributeGroupOne": "deneme main 2",
        "name": "Question_4",
        "weight": 4,
        "type": "radio",
        "options": {
            "1": "Çok Az",
            "2": "Az",
            "3": "Bazen",
            "4": "Genellikle",
            "5": "Her Zaman"
        }
    }],
    "surveyName": "deneme formu",
    "createdBy": {
        "$oid": "61becc2c230fc12274683b6a"
    },
    "createdAt": {
        "$date": "2022-03-10T02:05:54.039Z"
    },
    "updatedAt": {
        "$date": "2022-03-10T02:05:54.039Z"
    },
    "__v": 0
}

https://i.sstatic.net/xT2Cq.png

Without additional filter just by filtering category with following query I am getting reports that I wanted.

      .aggregate([
        { $unwind: '$answers' },
        {
          $group: {
            _id: '$answers.SubCategory',
            CalculatedWeight: { $avg: '$answers.CalculatedWeight' },
            formId: { $first: formId }
          }
        },
        { $project: { _id: 1, CalculatedWeight: 1, formId: 1 } },
        { $out: 'results' }
      ])

results:

{
    "CalculatedWeight": 19.35483870967742,
    "formId": {
        "$oid": "62295d028b6b895048b7da92"
    }
}

https://i.sstatic.net/HxqBe.png

I successfully added age filtering with following block

const docs = await model
      .aggregate([
        {
          $match: {
            $and: [
              { age: { $gt: minAge, $lt: maxAge } },
              { formId: { $eq: formId } }
            ]
          }
        },
        { $unwind: '$answers' },
        {
          $group: {
            _id: '$answers.SubCategory',
            CalculatedWeight: { $avg: '$answers.CalculatedWeight' },
            formId: { $first: formId }
          }
        },
        { $project: { _id: 1, CalculatedWeight: 1, formId: 1 } },
        { $out: 'results' }
      ])

But I have 5 filters that are, gender, department, age, working years, and education level. If possible I want to be able to combine them with dynamic querying but I don't want to write 120 if cases for combining them. I can't think a way to programmatically filter and calculate according to filters.

Thank you in advance. The question itself might be unclear, sorry about it. I can elaborate if you point out where it is lacking.

Edit:
Filter types can be seen below. Age and working years will be a period with min and max values. If possible I want to be able to combine all filter types but it will probably statistically unreasonable due to the small pool of entries ~200. Most common combinations for filters are: Gender-Department-Age, Working Years- Department, Education - Gender.

Filters:
gender: String - enum
department: String - enum
age: Number - Min and Max
working years: Number - Min and Max
education: String - enum

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花落人断肠 2025-01-21 13:53:24

对于其他遇到同样问题的人,我是这样解决的。

在我的情况下,由于只有匹配查询会发生变化,因此我根据使用以下代码获得的查询参数构造了匹配查询。

var array = Object.entries(req.query)
    array.forEach(x => {
      var z = { [x[0]]: { $eq: x[1] } }
      matchTry.$and.push(z)
    })

输出:

{
        "$and": [
            {
                "department": {
                    "$eq": "IT"
                }
            },
            {
                "gender": {
                    "$eq": "male"
                }
            }
        ]
    }

然后将 mongoose 与它一起使用

const docs = await model
      .aggregate()
      .match(match)
      .exec()
    res.status(200).json({ data: docs })

For anyone else struggling with the same thing, I figured it out this way.

In my situation since only the match query is subject to change I constructed match queries according to query parameters I am getting with following code.

var array = Object.entries(req.query)
    array.forEach(x => {
      var z = { [x[0]]: { $eq: x[1] } }
      matchTry.$and.push(z)
    })

output:

{
        "$and": [
            {
                "department": {
                    "$eq": "IT"
                }
            },
            {
                "gender": {
                    "$eq": "male"
                }
            }
        ]
    }

Then use mongoose with it

const docs = await model
      .aggregate()
      .match(match)
      .exec()
    res.status(200).json({ data: docs })
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文