bug? keyPrefix not added to the KEYS command
Volox opened this issue · 6 comments
Hi,
i have a problem with the KEYS command and the use of keyPrefix
. It seems that using a prefixed connection the prefix is not passed to the KEYS command.
I created a simple snippet of code to reproduce the problem.
'use strict';
let Promise = require( 'bluebird' );
let Redis = require( 'ioredis' );
const prefix = 'NS:'
// Create an unprefixed connection
let redisNP = new Redis();
// Create an prefixed connection
let redisP = new Redis( {
keyPrefix: prefix,
} );
let key = 'test:namespace:test';
let matchKey = 'test:*:test';
const data = {
mytest: 'true',
'my test2': 5,
};
// Add a namespaced(prefixed) key
redisP.hmset( key, data )
.then( () => {
// Issue the keys command to the connections
return Promise
.props( {
// Try the prefixed connection
prefix: redisP.keys( matchKey ),
// Try the unprefixed connection
noPrefix: redisNP.keys( matchKey ),
// Try to manual add the prefix to the unprefixed connection
manualPrefix: redisNP.keys( prefix+matchKey ),
} );
} )
.then( results => {
// I have 0 prefixed keys, should be 1
console.log( 'Should be 1', results.prefix.length );
// I have 0 unprefixed keys, OK
console.log( 'Should be 0', results.noPrefix.length );
// I have 1 manually prefixed keys, OK
console.log( 'Should be 1', results.manualPrefix.length );
console.log( 'Results: %j', results );
} )
.catch( err => console.error( err, err.stack ) )
.then( () => {
return [
redisP.quit(),
redisNP.quit(),
];
} );
Actually it's not a bug. ioredis relies on the COMMAND
command of Redis to get the position of the keys in a command's parameters. For keys
(as well as scan
) command, Redis tells ioredis that it doesn't contain a key, so that ioredis won't prefix it.
Ah ok, i got the point.
But since i am requiring keys
it would be nice/useful to use this command transparently no?
How are you able to determine what keys you actually have in redis, if the keys parameter would be prefixed? This is not possible in that case, so if you want to have the keys command prefixed you might consider adding a arguments transformer to it to always prefix the argument. I do not recommend it though.
Ok,
but once i got the keys from the keys
command i cannot use them coherently with the other commands.
Here is an example:
// Just pretend that it works without promises/callbacks :)
// prefx: "NS:"
let keys = redisP.keys( '*' ); // keys = [ "key1", "NS:key2" ]
// This will NEVER get "key1" because the get is namespaced
let val = redisP.get( keys[0] );
// also i cannot get "NS:key2" because i will get "NS:NS:key2" instead
@Volox I agree with you that it is of course a little inconvenience for people who want to use the keyPrefix
option as namespaces in order to have multiple applications share a single redis instance.
However, keyPrefix
literally means prefix keys with a string, but the parameter of KEY
command is a pattern instead of a key name, so that it won't be prefixed.
It's not hard to make the pattern also be prefixed, but I don't want to let ioredis do too much magic. There are other commands that should be prefixed if we handle the KEYS
command, for instance, SCAN
.
I don't want to mislead people into thinking they can reply on the keyPrefix
as namespaces. For example, FLUSHDB
actually deletes all the keys in the redis instead of the keys whose name started with keyPrefix
.
The workaround is to create another instance for KEYS
and SCAN
command or just create a wrapper yourself.
Thanks to all for the support, I see there is no easy solution for this.