【问题标题】:MongoDB - Looking up documents based on criteria defined by the documents themselvesMongoDB - 根据文档本身定义的标准查找文档
【发布时间】:2021-05-23 15:32:23
【问题描述】:

总的来说,我正在尝试找到一种系统设计来快速查找其元数据与传入事件中捆绑的数据相匹配的存储对象。然而,哪些字段是必需的,它们本身就是存储对象的一部分,而不是我可以硬编码到查找查询中的字段。

我的系统有一个存储在 MongoDB 中的 policies 集合,其中的文档如下所示:

{
    id: 123,
    name: "Jason's Policy",
    requirements: {
        "var1": "aaa",
        "var2": "bbb"
        // could have any number more, and each policy can have different field/values under requirements
    }
}

我的系统收到如下所示的事件:

// Event 1 - matches all requirements under above policy
{
    id: 777,
    "var1": "aaa",
    "var2": "bbb"
}

// Event 2 - does not match all requirements from above policy since var1 is undefined
{
    id: 888,
    "var2": "bbb",
    "var3": "zzz"
}

当我收到事件时,如何有效地查找所有要求完全满足事件中收到的值的策略?

例如,在上面的示例数据中,事件 1 应该返回策略(因为 var1 和 var2 符合策略要求),但事件 2 应该返回策略(因为 var1 不匹配/丢失)。

我可以想到在应用程序服务器本身上执行此操作的蛮力方法(想想嵌套的 for 循环),但效率将是关键,因为我们每秒接收数百个事件。

我对可以满足一般问题的文档架构更改建议持开放态度(根据我们文档中定义的标准查找文档)。我也对解决该问题的任何总体设计建议持开放态度(也许有更好的方法来构建我们的系统以触发响应事件的政策行动)。

谢谢!

【问题讨论】:

  • 因此,要使事件与策略匹配,其所有键(id 除外)和值都必须与策略匹配,对吗?
  • 您好,有一个events 文档,您想获取所有符合所有需求策略的policies 文档。我说的对吗?
  • 是的!所有策略键和值都必须匹配。事件可能有额外的数据(我可以忽略),但我需要返回事件数据与所有“poicy.requirements”字段匹配的策略列表。

标签: mongodb performance database-design database-schema


【解决方案1】:

不确定具体的场景是什么,但可以在这里想到 2,

  1. 您需要完全匹配。为此,您可以运行以下querydb.getCollection('test').find({'requirements':{'var1':'aaa','var2':'bbb'}}) 要运行上述查询,您需要在对键 var1 和 var2 进行排序后保存需求对象。
  2. 您需要匹配所有存在的属性,并且不在乎策略集合中是否有任何额外内容。您需要更改存储为的策略,
{
        "_id" : ObjectId("603250b0775428e32b9b303f"),
        "id" : 123,
        "name" : "Jason's Policy",
        "requirements" : {
            "var1" : "aaa",
            "var2" : "bbb"
        },
        "requirements_search" : [ 
            "var1aaa", 
            "var2bbb", 
            "var3ccc"
        ]
    }

然后您可以运行以下查询,

db.getCollection('test').find({'requirements_search':{'$all' : ['var1aaa','var2bbb']}})

【讨论】:

  • 感谢您的解决方案!你的第二个答案接近我正在寻找的。一个区别是我需要匹配策略本身中存在的所有属性,并且我不关心事件中的任何额外属性。
【解决方案2】:

我在另一篇帖子中找到了我的问题的答案:Find Documents in MongoDB whose with an array field is a subset of a query array

MongoDB 提供了一个$setIsSubset 运算符,可以检查文档的数组值是否是查询中数组值的子集。转化为我的用例:如果给定策略的要求是事件元数据的子集,那么我知道事件数据完全满足该策略的要求。

为了完整起见,下面是解决我的问题的 MongoDB 聚合。我仍然需要研究是否有更有效的整体系统设计来满足我的需要,但至少,这个 Mongo 聚合将获取我需要的结果。

// Requires us to flatten policy requirements into an array like the following
//
// {    
//     "id" : 123,
//     "name" : "Jason's Policy",
//     "requirements" : [ 
//         "var1_aaa", 
//         "var2_bbb" 
//     ]
// }
//
// Event  matches all policy requirements and has extra unrelated attributes
// {
//     id: 777,
//     "var1": "aaa",
//     "var2": "bbb",
//     "var3": "ccc"
// }

db.collection.aggregate([
    {$project: {
        doc: '$$ROOT',
        isSubset: {$setIsSubset: ['$requirements', ['var1_aaa', 'var2_bbb', 'var3_ccc']]}
    }},
    {$match: {isSubset: true}},
    {$project: {_id: 0, 'doc.name': 1}}
])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2019-05-17
    • 2018-12-29
    • 1970-01-01
    • 2021-05-08
    • 1970-01-01
    • 2013-05-26
    相关资源
    最近更新 更多