使用 beginWith 使用 dynamoose .get 在排序键中搜索

问题描述

我开始在这里学习 Dynamodb,目前正在尝试在我的表上进行搜索,其中 PK 是分区键,SK 是范围键。 PK 包含电子邮件地址,而 SK 包含诸如 AB_STATEBC_STATEMY_STATE 之类的值。因此,我想在值以 MY_ 开头的 SK 中进行搜索,但我不完全确定如何使用 .get() 函数进行搜索

这是我的查询 Seller.get({ "PK": "imin@cats.com","SK" : "MY" }),它显然不是我想要的。

我知道我也许可以使用像下面这样的过滤器,但我在很多地方读到不推荐使用过滤器 (?)

var filter = new dynamoose.Condition().where("PK").eq(email).filter("SK").beginsWith("MY_");
var premiseProfile = await Seller.query(filter).exec()

以下是我的卖家表的架构

const schema = new dynamoose.Schema({
    PK: {
        type: String,hashKey: true,},SK: {
        type: String,rangeKey: true,"firstName": String,"lastName": String,"gender": {
        "type": Number,"default": 0
    },{
    "saveUnkNown": true,"timestamps": true
});

解决方法

执行 Model.get 调用时,您必须传入整个密钥。您不能传入以 开头的键。这是因为 Model.get 将只返回 1 个项目,并且查询表明您可以在那里有多个项目。

由于您没有发布架构,因此很难准确回答您的问题。但在这种情况下执行 query 看起来还不错,因为您是在查询数据而不是过滤数据。


基于评论的更多信息。

我意识到 condition.filter documentation 并没有真正涵盖这一点。基本上取决于您的架构,它将确定最佳索引,并以它知道的最佳方式对其进行优化。

例如,如果您有以下代码:

const dynamoose = require("dynamoose");

(async () => {
    dynamoose.model.defaults.set({
        "create": false,"waitForActive": false
    });

    const schema = new dynamoose.Schema({
        "PK": {
            "type": String,"hashKey": true
        },"SK": {
            "type": String,"rangeKey": true
        }
    });

    const Model = dynamoose.model("User",schema);

    dynamoose.logger.providers.add(console);

    const filter = new dynamoose.Condition().where("PK").eq("test@test.com").filter("SK").beginsWith("MY_");
    const premiseProfile = await Model.query(filter).exec()
})();

它将产生以下输出:

aws:dynamodb:query:request - {
    "ExpressionAttributeNames": {
        "#qha": "PK","#qra": "SK"
    },"ExpressionAttributeValues": {
        ":qhv": {
            "S": "test@test.com"
        },":qrv": {
            "S": "MY_"
        }
    },"TableName": "User","KeyConditionExpression": "#qha = :qhv AND begins_with (#qra,:qrv)"
}

如您所见,它使用的是 KeyConditionExpression 而不是 FilterExpression

所以你没有过滤。如果对您更有意义,您可以使用 condition.wherecondition.attribute

需要注意的是,在某些情况下它会使用 FilterExpression。但它会首先查看您的架构并尝试查看它是否可以使用 KeyConditionExpression,如果可以,它将使用它,否则它将使用 FilterExpression