¿Por qué DynamoDB escanea con Limit y FilterExpression no devuelve los elementos que coinciden con los requisitos del filtro?

Necesito hacer un escaneo con límite y una condición en DynamoDB.

La documentación dice:

En una respuesta, DynamoDB devuelve todos los resultados coincidentes dentro del scope del valor límite. Por ejemplo, si emite una consulta o una solicitud de exploración con un valor límite de 6 y sin una expresión de filtro, DynamoDB devuelve los primeros seis elementos de la tabla que coinciden con las condiciones clave especificadas en la solicitud (o solo los primeros seis elementos en la tabla). El caso de un escaneo sin filtro). Si también proporciona un valor de FilterExpression, DynamoDB devolverá los elementos de los primeros seis que también coincidan con los requisitos del filtro (el número de resultados devueltos será menor o igual a 6).

El código (NODEJS):

var params = { ExpressionAttributeNames: {"#user": "User"}, ExpressionAttributeValues: {":user": parseInt(user.id)}, FilterExpression: "#user = :user and attribute_not_exists(Removed)", Limit: 2, TableName: "XXXX" }; DynamoDB.scan(params, function(err, data) { if (err) { dataToSend.message = "Unable to query. Error: " + err.message; } else if (data.Items.length == 0) { dataToSend.message = "No results were found."; } else { dataToSend.data = data.Items; console.log(dataToSend); } }); 

Tabla XXXX definiciones:

  • Clave de partición primaria: Usuario (Número)
  • Clave de clasificación primaria: Identificador (String)
  • ÍNDICE:
    • Nombre del índice: RemovedIndex
    • Tipo: GSI
    • Clave de partición: Eliminada (Número)
    • Clave de clasificación: –
    • Atributos: TODOS

En el código anterior, si elimino el parámetro Limit , DynamoDB devolverá los elementos que coincidan con los requisitos del filtro. Por lo tanto, las condiciones están bien. Pero cuando escaneo con el parámetro Limit , el resultado está vacío.

La mesa XXXX, tiene 5 elementos. Solo los 2 primeros tienen el atributo Removed . Cuando escaneo sin el parámetro Limit , DynamoDB devuelve los 3 elementos sin el atributo Removido.

¿Qué estoy haciendo mal?

De los documentos que citó:

Si también proporciona un valor de FilterExpression, DynamoDB devolverá los elementos de los primeros seis que también cumplen con los requisitos de filtro

Al combinar Limit y FilterExpression, le ha dicho a DynamoDB que solo mire los dos primeros elementos de la tabla y evalúe FilterExpression contra esos elementos. El límite en DynamoDB puede ser confuso porque funciona de manera diferente al limit en una expresión SQL en un RDBMS.

También encontré este problema, supongo que solo tendrá que escanear toda la tabla a un máximo de 1 MB

Escaneo El conjunto de resultados de un Escaneo está limitado a 1 MB por llamada. Puede usar el LastEvaluatedKey de la respuesta de escaneo para recuperar más resultados.

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html

Es posible que pueda obtener lo que necesita utilizando un índice secundario. Utilizando el ejemplo clásico de RDB, ejemplo de pedido de cliente: tiene una tabla para clientes y otra para pedidos. La tabla de Órdenes tiene una Clave que consiste en Cliente – HASH, Orden – RANGO. Entonces, si quisiera obtener los últimos 10 pedidos, no habría manera de hacerlo sin un escaneo

Pero si crea un Índice Secundario Global en órdenes de “Alguna Constante”: HASH, RANGO DE FECHA y consulta contra ese índice, la consulta hará lo que usted desea y le cobrará únicamente las RCU involucradas con los registros devueltos. No se necesita un escaneo costoso. Tenga en cuenta que las escrituras serán más caras, pero en la mayoría de los casos, hay muchas más lecturas que escrituras.

Ahora tiene su problema original si desea obtener los 10 pedidos más grandes para un día superior a $ 1000. La consulta devolvería los últimos 10 pedidos y luego filtraría aquellos menos de $ 1000.

En este caso, podría crear una clave calculada de Date-OrderAmount, y las consultas contra ese índice devolverán lo que desea.

No es tan simple como SQL, pero también debe pensar en los patrones de acceso en SQL. Si tiene muchos datos, necesita crear índices en SQL o la base de datos estará encantada de presentar escaneos en su nombre, lo que perjudicará el rendimiento y boostá sus costos.

Tenga en cuenta que todo lo que propuse está normalizado en el sentido de que solo hay una fuente de verdad. No está duplicando datos, simplemente está revisando vistas para obtener lo que necesita de DynamoDB.

Tenga en cuenta que el CONSTANTE como HASH está sujeto al límite de 10 GB por partición, por lo que tendría que diseñar alrededor de él si tuviera muchos datos activos. Por ejemplo, dependiendo de su patrón de acceso esperado, podría usar Cliente y no una constante como HASH. O use STreams para organizar los datos (o subconjuntos) de otras maneras.