简体   繁体   English

DynamoDB:查询以查找字符串数组中的项

[英]DynamoDB: Query to find an item in an array of strings

It's possible that I'm not quite understanding how hash/primary keys work in DynamoDB, but I'm trying to create a model (using Serverless + Dynogels/NodeJS) for a messaging service. 可能我不太了解哈希/主键在DynamoDB中的工作方式,但是我正在尝试为消息传递服务创建一个模型(使用Serverless + Dynogels / NodeJS)。

The model looks like this: 该模型如下所示:

const ConversationORM = dynogels.define('Conversation', {

  hashKey: 'id',

  timestamps: true,
  tableName: config.CONVERSATION_TABLE,

  schema: {

    id: Joi.string(),
    users: Joi.array(), // e.g. ['foo', 'bar', 'moo']
    messages: Joi.array()

  }
})

As you can see, users is an array, which lists the userIds of the conversation's participants. 如您所见, users是一个数组,其中列出了对话参与者的userIds。

I need to create a service which finds all conversations that a user is participating in. In MongoDB (which I'm far more familiar with), I'd do something like: 我需要创建一个服务来查找用户参与的所有对话。在MongoDB(我更加熟悉)中,我将执行以下操作:

Conversation.find({users: {"$in": ['foo']} }).then(.... 

Is there something equivalent I can do in DynamoDB? 我可以在DynamoDB中做一些等效的事情吗? This is an API call that will happen quite often so I'm hoping to make it as efficient as possible. 这是一个经常发生的API调用,因此我希望使其尽可能高效。

This answer takes into account a comment on Hunter Frazier's answer saying you don't want to use a Scan. 该答案考虑了对Hunter Frazier答案的评论,即您不想使用扫描。

When using a Query you need specify a single partition key in the operation. 使用查询时,您需要在操作中指定一个分区键。 In your schema this would mean partitioning on the userid attribute, which is a set. 在您的架构中,这将意味着在userid属性(这是一个集合)上进行分区。 Partition keys in DynamoDB must be a top-level scalar attribute. DynamoDB中的分区键必须是顶级标量属性。 As userid is not scalar (its a set), you cannot use this attribute as an index, and therefore you cannot do a Query for the conversations a user is part of. 由于userid不是标量(它是一个集合),因此不能将此属性用作索引,因此无法对用户所属的对话进行查询。

If you need to do this Query, I would suggest revisiting your schema. 如果您需要执行此查询,建议您重新访问架构。 Specifically I would suggest implementing the Adjacency list pattern which works well in databases containing many-to-many relationships. 具体来说,我建议实现邻接列表模式 ,该模式在包含多对多关系的数据库中效果很好。

You can see some additional notes on the article above I have written on this answer DynamoDB MM Adjacency List Design Pattern 您可以在上面我在此答案上写过的文章上看到一些其他注释, DynamoDB MM邻接列表设计模式

In your case you would have: 您的情况是:

  • Primary Key: ConversationID 主键:ConversationID
  • Sort Key: UserID 排序键:UserID
  • GSI Primary Key: UserID GSI主键:UserID

You can then use the GSI Primary key in a Query to return all conversations the user is part of. 然后,您可以在查询中使用GSI主键来返回用户所属的所有对话。

I'm not familiar with Dynogels or Serverless but if it uses the regular API this might work: 我不熟悉Dynogels或Serverless,但如果它使用常规API,则可能会起作用:

var params = {
    ExpressionAttributeNames: {
        "U": "users"
    },
    ExpressionAttributeValues: {
        ":a": {
            S: "John Doe"
        }
    },
    FilterExpression: "Author = :a",
    ProjectionExpression: "#U",
    TableName: "Conversations"
};
dynamodb.scan(params, function (err, data) {
    if (err) console.log(err, err.stack);
    else console.log(data);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM