DynamoDB, как делать запросы с помощью BEGINS_WITH

Я использую DocumentClient для запроса. и используя бессерверную структуру с DynamoDb.

Я пытаюсь выполнить запрос с помощью BEGINS_WITH без предоставления какого-либо первичного ключа.

вот как выглядят мои данные:

[
  {
    id: 1,
    some_string: "77281829121"
  },
  {
    id: 2,
    some_string: "7712162hgvh"
  },
  {
    id: 3,
    some_string: "7212121"
  }
]

вот мой serverless.yml [я думаю, конфигурация таблицы]:

Resources:
 IPRecord:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        TableName: ${file(./serverless.js):Tables.IPRecord.name}
        BillingMode: PAY_PER_REQUEST
        AttributeDefinitions:
          - AttributeName: 'id'
            AttributeType: 'S'
          - AttributeName: 'some_string'
            AttributeType: 'S'
        KeySchema:
          - AttributeName: 'id'
            KeyType: 'HASH'
        GlobalSecondaryIndexes:
          - IndexName: ${file(./serverless.js):Tables.IPRecord.index.ID}
            KeySchema:
              # ...some more index goes here
              - AttributeName: 'some_string'
                KeyType: 'RANGE'
            Projection:
              ProjectionType: 'ALL'

Q: Используя DocumentClinet, я хочу запросить несколько первых элементов some_string. который вернет все совпадающие документы. как в этом случае я хочу запросить {some_string:"77"}, и он вернет

 [{
    id: 1,
    some_string: "77281829121"
  },
  {
    id: 2,
    some_string: "7712162hgvh"
  }]

в настоящее время мой запрос выглядит так [это дает ошибку] ​​[Выполняется в локальной оболочке DynamoDB JS]:

var params = {
    TableName: '<TABLE_NAME>',
    IndexName: '<INDEX_NAME>',
    KeyConditionExpression: 'begins_with(some_string,:value)',
    ExpressionAttributeValues: { 
      ':value': '77'
    }
};
docClient.query(params, function(err, data) {
    if (err) ppJson(err);
    else ppJson(data); 
});

похоже, что для этого запроса требуется первичный ключ, и в моем случае это id. если я передам это, он будет указывать на один документ.

Вот чего я добился на данный момент:

var params = {
    TableName: '<TABLE_NAME>',
    FilterExpression: 'begins_with(some_string,:value)',
    ExpressionAttributeValues: { 
      ':value': '77'
    },
    Select:'COUNT' //as i only required COUNT
};
docClient.scan(params, function(err, data) {
    if (err) ppJson(err);
    else ppJson(data); 
});

этот запрос делает то, что я хочу. Но любой лучший подход или решение всегда приветствуются.


person Saikat Chakrabortty    schedule 05.02.2019    source источник
comment
каков вариант использования, который вы пытаетесь решить, Dynamodb не поддерживает, начинается с без первичного ключа.   -  person best wishes    schedule 05.02.2019
comment
@bestwishes, поэтому я пытаюсь получить все документы, в которых some_string начинается, скажем, с 77,   -  person Saikat Chakrabortty    schedule 05.02.2019
comment
это план :), который не будет работать (по крайней мере, с этим подходом), но что такое some_string, как они связаны,   -  person best wishes    schedule 05.02.2019
comment
извини, я не могу тебя правильно поймать. но да, some_string - строковое поле, может содержать случайную строку. как 2_. Если вы посмотрите на serverless.yml, которое вы также можете получить, я добавил для этого GSI.   -  person Saikat Chakrabortty    schedule 05.02.2019


Ответы (1)


если количество символов в вашем запросе beginwith всегда будет случайным, я не вижу возможности решить эту проблему с помощью Dynamodb.

но предположим, что будет как минимум 3 символа. тогда вы можете сделать следующее.

Обновите схему Dynamodb до

 IPRecord:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        TableName: ${file(./serverless.js):Tables.IPRecord.name}
        BillingMode: PAY_PER_REQUEST
        AttributeDefinitions:
          - AttributeName: 'id'
            AttributeType: 'S'
          - AttributeName: 'some_string'
            AttributeType: 'S'
        KeySchema:
          - AttributeName: 'id'
            KeyType: 'HASH'
          - AttributeName: 'some_string'
            KeyType: 'RANGE'

И вместо хранения

[
  {
    id: 1,
    some_string: "77281829121"
  },
  {
    id: 2,
    some_string: "7712162hgvh"
  },
  {
    id: 3,
    some_string: "7212121"
  }
]

хранить как

[
  {
    id: 772,
    uniqueid:1,
    some_string: "77281829121"
  },
  {
    id: 771,
    uniqueid:2,
    some_string: "7712162hgvh"
  },
  {
    id: 721,
    uniqueid:3,
    some_string: "7212121"
  }
]

Где id - всегда первые 3 символа исходной some_string.

Теперь предположим, что вам нужно запросить все элементы, которые начинаются с abcx, вы можете сделать

select * where id=abc and some_string startswith abcx

но вы всегда должны стараться иметь больше символов в идентификаторе, чтобы нагрузка распределялась случайным образом. например, если есть только 2 символа, возможно только 36 * 36 идентификаторов, если есть 3 символа, возможно 36 * 36 * 36 идентификаторов.

person best wishes    schedule 06.02.2019
comment
number of characters in your beginswith query is always going to be random, это всегда будет случайным. нет никакой связи с полем id прямо сейчас с. хотя сейчас я использую .scan, который также возвращает ожидаемые данные. но не кажется эффективным. - person Saikat Chakrabortty; 06.02.2019
comment
@saikat да, я говорю, скажем, в вашем запросе всегда будет 3 символа, сделайте эти 3 символа первичным ключом. так что вы можете запрашивать вместо сканирования. - person best wishes; 06.02.2019
comment
понял, теперь дело в том, что когда я собираюсь искать, скажем, 5 символов, это увеличит сложность. также это 3 символа, если я сделаю их идентификатором, в любое время, когда это может вызвать конфликт. так что id больше не будет уникальным. - person Saikat Chakrabortty; 06.02.2019
comment
вы можете обновить свою схему, чтобы в качестве ключа сортировки использовалась some_string. после этого id не обязательно должен быть уникальным, id + some_string должен быть уникальным, вы можете уйти от GSI1, поскольку это в любом случае не решает никаких задач. - person best wishes; 06.02.2019
comment
i'm going to search with say 5chars then it will increase the complexity. это не вызовет никаких проблем, если у вас есть минимальный запрос в качестве идентификатора. - person best wishes; 06.02.2019
comment
извините, к сожалению, это не так, но я ценю эту идею. для моего варианта использования это довольно сложно, поскольку в нем есть некоторые зависимые вещи. ищу еще несколько подходов. - person Saikat Chakrabortty; 06.02.2019