查询Dynamodb

时间:2018-05-24 11:47:16

标签: amazon-web-services indexing nosql amazon-dynamodb

如何在Dynamodb中有效查询嵌套属性?

我有一个如下文档结构,它允许我将相关信息存储在文档中(而不是引用它)。

存储嵌套在课程中的研讨会是有意义的,因为它们可能会在课程中被查询(它们都是课程特定的,即课程有很多研讨会,研讨会属于课程)。

在我迁移的CouchDB中,我可以编写一个View,它会为查询投射一些嵌套属性。我知道我不能将任何不是顶级属性的东西投射到dynamodb二级索引中,所以这种方法似乎不起作用。

这让我回到了这个问题:如果我不能将它们用作索引中的键,我如何在不扫描的情况下有效地查询嵌套属性?

例如,如果我想获得纳尔逊曼德拉剧院的平均出勤率,我如何在所有位于“纳尔逊曼德拉剧院”的研讨会中查询registrationsattendees的值。不求助于扫描?

{
    “course_id”: “ABC-1234567”,
    “course_name”: “Statistics 101”,
    “tutors”: [“Cognito-sub-1”, “Cognito-sub-2”],
    “seminars”: [ 
        {
            “seminar_id”: “XXXYYY-12345”,
            “epoch_time”: “123456789”,
            “duration”: “5400”,
            “location”: “Nelson Mandela Theatre”,
            “name”: “How to lie with statistics”,
            “registrations”: “92”,                
            “attendees”: “61”
        },
        {
            “seminar_id”: “BBBCCC-44444”,
            “epoch_time”: “155555555”,
            “duration”: “5400”,
            “location”: “Nelson Mandela Theatre”,
            “name”: “Statistical significance for dog owners”,
            “registrations”: “244”,
            “attendees”: “240”
        },
        {
            “seminar_id”: “XXXAAA-54321”,
            “epoch_time”: “223456789”,
            “duration”: “4000”,
            “location”: “Starbucks”,
            “name”: “Is feral cat population growth a leading indicator for the S&P 500?”,
            “registrations”: “40”                
        }
    ]
}

{
    “course_id”: “CJX-5553389”,
    “course_name”: “Cat Health 101”,
    “tutors”: [“Cognito-sub-4”, “Cognito-sub-9”],
    “seminars”: [ 
        {
            “seminar_id”: “TTRHJK-43278”,
            “epoch_time”: “123456789”,
            “duration”: “5400”,
            “location”: “Catwoman Hall”,
            “name”: “Emotional support octopi for cats”,
            “registrations”: “88”, 
            “attendees”: “87”
        },
        {
            “seminar_id”: “BBBCCC-44444”,
            “epoch_time”: “123666789”,
            “duration”: “5400”,
            “location”: “Nelson Mandela Theatre”,
            “name”: “Statistical significance for cat owners”,
            “registrations”: “44”,
            “attendees”: “44”
        }
    ]
}

5 个答案:

答案 0 :(得分:6)

无法为嵌套属性(即Dynamodb中的文档数据类型)创建索引。

  

文档类型 - 文档类型可以表示复杂的结构   使用嵌套属性 - 例如您可以在JSON文档中找到的属性。该   文档类型是列表和地图。

查询Api: -

查询操作仅搜索主键属性值,并支持关键属性值的比较运算符子集,以优化搜索过程。

扫描API: -

扫描操作扫描整个表格。您可以指定过滤器以应用于结果,以在完整扫描后优化返回给您的值。

为了使用Query API,需要哈希键值。 OP没有任何散列键值可用的信息。根据OP,数据需要通过Dynamodb location数据类型内的List属性进行查询。现在,选择是看GSI。

请详细了解GSI。其中一条规则是GSI只能使用顶级属性创建。因此,该位置不能用于创建索引。

因此,为了使用查询API而创建GSI也已被排除。

  

索引键属性可以包含任何顶级字符串Number,   或基表中的二进制属性;其他标量类型,文档   不允许使用类型和集合类型。

由于上述原因,我们无法使用查询API来获取基于location属性的数据,假设哈希键值不可用。

如果哈希键值可用,FilterExpression可用于过滤数据。过滤复杂列表数据类型中存在的数据的唯一方法是CONTAINS函数。为了使用CONTAINS函数,事件中的所有属性都需要与数据匹配(即seminar_id,location,duration和所有其他属性)。因此,绝对不可能使用当前数据模型来满足OP中提到的用例。

建议的替代解决方案: -

如下所述对数据结构进行重新建模可能是解决问题的一种方法。绝对没有其他解决方案可以使用Query API来完成用例。

主要表: -

课程ID - 哈希键

seminar_id - 排序键

GSI: -

研讨会地点 - 哈希键

课程ID - 排序键

  

在DynamoDB表中,每个键值必须是唯一的。但是,关键   global secondary index中的值不需要是唯一的。

现在,您可以使用GSI上的查询API来获取Seminar location的数据等于Nelson Mandela Theatre。如果您知道值,则可以在查询api中使用课程ID。查询api可能会在结果集中提供多个项目。如果您希望根据某些非关键属性进一步过滤数据,则可以使用FilterExpression

答案 1 :(得分:0)

您可以做一件事以使其在Scan上运行 以stringify格式存储对象,例如 { “ language”:“ [{\” language \“:\” Male \“,\”熟练程度“:\”女性\“}]”“ }'' 然后可以执行扫描操作       语言: {             包含:“男”     }

在客户端,您可以执行JSON.parse(language)

答案 2 :(得分:0)

我还没有使用DynamoDB的经验,但是因为我打算在下一个项目中使用它,所以开始研究它。

据我从AWS文档中了解的,您的问题的答案是:无法高效地查询嵌套属性。

着眼Best Practices,特别是Best Practices for Using Secondary Indexes in DynamoDB,可以理解正确的方法应该在与here相同的分区键下使用不同的线型。然后在相同的course_id下,您将拥有一个通用的排序键(sk)。然后,第一个寄存器将带有课程数据的sk ='Details',然后是其他寄存器,例如“ seminar-1”及其数据,依此类推。 然后,您要设置研讨会的属性,并将其作为SGI(二级全球索引)进行查询,但要记住,每个表只能包含5个SGI。

希望有帮助。

答案 3 :(得分:0)

这是一个来自here的示例,其中使用了一个过滤器表达式,它带有扫描操作,但也许您可以对查询应用类似的内容而不是扫描(看看API ):

{
    "TableName": "MyTable",
    "FilterExpression": "#k_Compatible.#k_RAM = :v_Compatible_RAM",
    "ExpressionAttributeNames": {
        "#k_Compatible": "Compatible",
        "#k_RAM": "RAM"
    },
    "ExpressionAttributeValues": {
        ":v_Compatible_RAM": "RAM1"
    }
}

答案 4 :(得分:0)

您可以使用document paths来过滤值。使用workshops.location作为文档路径。