Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

find ignores index search key expression #530

Closed
stabl-gjn opened this issue Jun 6, 2024 · 3 comments
Closed

find ignores index search key expression #530

stabl-gjn opened this issue Jun 6, 2024 · 3 comments
Labels
discussion Question or issue being discussed

Comments

@stabl-gjn
Copy link

stabl-gjn commented Jun 6, 2024

Describe the bug

When using find together with an index and defining a key condition on the SK of the index, onetable will ignore the condition.
The operation will succeed and even return items, but when looking at the debug log, no key expression for the SK is applied only the PK.

The same find expression (without the index) does work if the index SK expression (_gs1sk) is used as the normal entity sk and the find is run on it.

Cut/Paste

SCHEMA

const schema = {
	format: "onetable:1.1.0",
	version: "0.0.1",
	params: {
		timestamps: true,
		isoDates: false,
	},
	indexes: {
		primary: { hash: "pk", sort: "sk" },
		gs1: {
			hash: "_gs1pk",
			sk: "_gs1sk",
			project: "keys",
		},
	},
	models: {
		Token: {
			pk: { type: String, value: "registration#${user}" },
			sk: { type: String, value: "token#${key}" },
			user: {
				type: String,
				required: true,
				encode: ["pk", "#", 1],
			},
			key: {
				type: String,
				required: true,
				validate: MATCH.token,
				encode: ["sk", "#", 1],
			},
			expires: { type: Date, required: true, ttl: true },
			updated: { type: Date },
			created: { type: Date },

			// Index Keys
			_gs1pk: {
				type: String,
				value: "token#${key}",
				hidden: true,
			},
			_gs1sk: {
				type: String,
				value: "token#${expires}",
				hidden: true,
			},
		},
	} as const,
} as const;

CODE

const token = await TOKENS.find(
	{
		_gs1pk: "token#ASD12",
		_gs1sk: { ">": "token#1" },
	},
	{
		index: "gs1",
		log: true,
	},
);

LOG

info OneTable "find" "Token" {
    "trace": {
        "model": "Token",
        "cmd": {
            "ExpressionAttributeNames": {
                "#_0": "_gs1pk"
            },
            "ExpressionAttributeValues": {
                ":_0": {
                    "S": "token#ASD12"
                }
            },
            "KeyConditionExpression": "#_0 = :_0",
            "TableName": "asdf",
            "ConsistentRead": false,
            "IndexName": "gs1",
            "ScanIndexForward": true
        },
        "op": "find",
        "properties": {
            "_gs1pk": "token#ASD12"
        }
    }
}
info OneTable result for "find" "Token" {
    "cmd": {
        "ExpressionAttributeNames": {
            "#_0": "_gs1pk"
        },
        "ExpressionAttributeValues": {
            ":_0": {
                "S": "token#ASD12"
            }
        },
        "KeyConditionExpression": "#_0 = :_0",
        "TableName": "asdf",
        "ConsistentRead": false,
        "IndexName": "gs1",
        "ScanIndexForward": true
    },
    "items": [],
    "op": "find",
    "properties": {
        "_gs1pk": "token#ASD12"
    },
    "params": {
        "parse": true,
        "high": true,
        "index": "gs1",
        "log": true,
        "checked": true
    }
}

Expected behavior
A clear and concise description of what you expected to happen.

Works when normal entity pk/sk is used:

Details

SCHEMA (only delta)

Token: {
	pk: { type: String, value: "token#${key}" },
	sk: { type: String, value: "token#${expires}" },
}

CODE

const token = await TOKENS.find(
	{
		pk: "token#ASD12",
		sk: { ">": "token#1" },
	},
	{
		log: true,
	},
);

LOGS

info OneTable "find" "Token" {
    "trace": {
        "model": "Token",
        "cmd": {
            "ExpressionAttributeNames": {
                "#_0": "pk",
                "#_1": "sk"
            },
            "ExpressionAttributeValues": {
                ":_0": {
                    "S": "token#ASD12"
                },
                ":_1": {
                    "S": "token#1"
                }
            },
            "KeyConditionExpression": "#_0 = :_0 and #_1 > :_1",
            "TableName": "asdf",
            "ConsistentRead": false,
            "ScanIndexForward": true
        },
        "op": "find",
        "properties": {
            "pk": "token#ASD12",
            "sk": {
                ">": "token#1"
            }
        }
    }
}
info OneTable result for "find" "Token" {
    "cmd": {
        "ExpressionAttributeNames": {
            "#_0": "pk",
            "#_1": "sk"
        },
        "ExpressionAttributeValues": {
            ":_0": {
                "S": "token#ASD12"
            },
            ":_1": {
                "S": "token#1"
            }
        },
        "KeyConditionExpression": "#_0 = :_0 and #_1 > :_1",
        "TableName": "asdf",
        "ConsistentRead": false,
        "ScanIndexForward": true
    },
    "items": [],
    "op": "find",
    "properties": {
        "pk": "token#ASD12",
        "sk": {
            ">": "token#1"
        }
    },
    "params": {
        "parse": true,
        "high": true,
        "log": true,
        "checked": true
    }
}

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • OS: Linux
  • OneTable Version: 2.7.2
@mobsense
Copy link
Contributor

Thanks for raising, we'll check this and get back to you.

@mobsense
Copy link
Contributor

A couple of issues with your test code and the issue seems fixed.

In your index:

	indexes: {
		primary: { hash: "pk", sort: "sk" },
		gs1: {
			hash: "_gs1pk",
			sk: "_gs1sk",
			project: "keys",
		},

Your gs1 "sk" property should be "sort".

In your test code:

const token = await TOKENS.find({
	_gs1pk: "token#ASD12",
	_gs1sk: { ">": "token#1" },
}, {
		index: "gs1",
});

Your gs1pk and gs1sk values are wrong. They should be "token#1" and "token#EXPIRES_VALUE".

Can I please also ask one and all that a complete debug.ts is much better than fragements of code. Despite this case being really well documented -- a debug.ts saves us a lot of time just to replicate the issue. It takes about 30 minutes to construct a test case for such issues. Doesn't sound like much, but we do this for free and those 30 minutes really add up over time.

@mobsense mobsense added the discussion Question or issue being discussed label Jun 28, 2024
@stabl-gjn
Copy link
Author

@mobsense thanks for taking the time and look into this and doing the write up. Also sorry for not providing a full example, will remember to do so next time.

I missed the sk => sort and will try with that again.
As for the values i don't think the are mixed up, the intention is to query for a specific token key and a expiry where the first digit is bigger than 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Question or issue being discussed
Projects
None yet
Development

No branches or pull requests

2 participants