Node.js & redis / zadd objects to a set
Solution 1
Issue 1 -- sorted set keys
Try stringifying the JSON you are using as the keys of your sorted set. For example,
dbclient1.zadd("myprivateset", 3, {"guid":"abab-baba", "data-persistent":"xxxx", "size":"20"})
needs to be:
dbclient1.zadd("myprivateset", 3, JSON.stringify({"guid":"abab-baba", "data-persistent":"xxxx", "size":"20"}))
Without stringifying the keys, every zadd will use the key [object Object]
overwriting each time. That is, you'll only ever have one item in your sorted set that is unidentifiable (other than by [object Object]
).
Issue 2 -- fetching data
Also, hgetall
is not the redis command to use for retrieving data in a redis sorted set. You'll want to focus on sorted set specific commands. A list of redis commands are listed here: http://redis.io/commands
Solution 2
My two cents, building on comments by @leonid-beschastny and @cpentra1. I recommend using redis.multi()
. It allows for several calls in a batch, and as you can see in the example, as soon as the three elements are added to the ordered set, we can perform a zrangebyscore
in the same multi
batch and get the expected results. Instructions can be created dynamically. The replies
array when multi.exec()
is invoked returns the results for each of the multi
operations, in order.
var db = require("redis");
var dbclient1 = db.createClient();
var multi = dbclient1.multi();
// We use JSON.stringify() as suggested by @cpentra1
multi.zadd("myprivateset", 3, JSON.stringify({"guid":"abab-baba", "data-persistent":"xxxx", "size":"20"}));
multi.zadd("myprivateset", 2, JSON.stringify({"guid":"abab-baba3", "data-persistent":"xxxx", "size":"20"}));
multi.zadd("myprivateset", 2, JSON.stringify({"guid":"abab-dafa3", "data-persistent":"yyyy", "size":"21"}));
multi.zrangebyscore("myprivateset", 1, 4);
multi.zcard("myprivateset"); // The total number of elements in the set
multi.exec(function(err, replies) {
console.log(replies)
// Will output something like:
// [ 1,
// 1,
// 1,
// [ '{"guid":"abab-baba3","data-persistent":"xxxx","size":"20"}',
// '{"guid":"abab-dafa3","data-persistent":"yyyy","size":"21"}',
// '{"guid":"abab-baba","data-persistent":"xxxx","size":"20"}' ],
// 3 ]
});
Note: if you run the same example twice, instead of 1
s in the first three elements of the replies
array, you'll get 0
s as the same member with the same score cannot be added twice.
Solution 3
Seems like with Redis 6.2 the format has changed to and object with score
and value
attributes or an array of those, like this:
async function sortedSet() {
let client;
try {
client = createClient();
client.on("error", (err) => console.log("Redis Client Error", err));
await client.connect();
console.log("connected");
await client.zAdd("user:0:followers", [{score: "1", value: "John"}, {score: "2", value: "Other John"}]);
console.log("sorted set added");
} finally {
await client.quit();
}
}
sortedSet("duto_guerra", "with hashes");
In case you are wondering, I figured this out by reading the source code for node-redis ZADD
Related videos on Youtube
MIDE11
Updated on September 16, 2022Comments
-
MIDE11 over 1 year
I have the following code:
var db = require("redis"); var dbclient1 = db.createClient(); dbclient1.zadd("myprivateset", 3, {"guid":"abab-baba", "data-persistent":"xxxx", "size":"20"}) dbclient1.zadd("myprivateset", 2, {"guid":"abab-baba3", "data-persistent":"xxxx", "size":"20"}) dbclient1.zrangebyscore("myprivateset", 1, 4) dbclient1.hgetall("myprivateset", function(err, rep){ console.log(rep); });
I wish to store my objects (in JSON format) in a sorted set, which determine by the score (3 & 2 in our case).
For some reason, when I print this table (
rep
), I get undefined.What I do wrong?
-
MIDE11 almost 9 yearsIt still prints undefined
-
cpentra1 almost 9 yearsI don't think hgetall is what you want.
-
cpentra1 almost 9 years// returns all in score range from 1-4
dbclient1.zrangebyscore("myprivateset", 1, 4, function(err, rep) { console.log(rep); });
// returns paginated from 0 to 5dbclient1.zrevrange("myprivateset", 0, 5, function(err, rep) { console.log(rep); });
-
cpentra1 almost 9 yearsHGETALL is for hashes, and you're using a sorted set so you'll want to use sorted set retrieval methods instead of hash ones to access the data. (redis.io/commands)
-
kdragger over 2 yearsthanks. i was getting super frustrated and the docs don't mention sorted sets specifically, that it is zAdd (not zadd), or this new format.
-
Nandeep Mali about 2 yearsThank you for this. Had no idea that we had to use a list of score and value pairs. Really got me frustrated.