Add a value to the Redis list only if it does not already exist in the list?

I am trying to add a value to the list, but only if it has not been added yet.

Is there a command for this or is there a way to check if a value is in the list?

Thanks!

+5
source share
7 answers

I need to do the same. I am thinking of removing an item from the list and then adding it again. If the item is not in the list, redis will return 0, so there is no error

lrem mylist 0 myitem rpush mylist myitem 
+8
source

As Tommaso Barbugli said, you should use a set instead of a list if you only need unique values. see the REDIS SADD documentation

 redis> SADD myset "Hello" (integer) 1 redis> SADD myset "World" (integer) 1 redis> SADD myset "World" (integer) 0 redis> SMEMBERS myset 1) "World" 2) "Hello" 

If you want to check for a value in a set, you can use SISMEMBER

 redis> SADD myset "one" (integer) 1 redis> SISMEMBER myset "one" (integer) 1 redis> SISMEMBER myset "two" (integer) 0 
+4
source

It looks like you need a set or sorted set.

Kits have an O (1) membership test and forced uniqueness.

+2
source

Such a function is available in a set using the hexists hexists command in redis.

+1
source

Checking the list to see if an item exists inside it is O (n), which can become quite expensive for large lists and is definitely not ideal. However, everyone else seems to give you alternatives. I will just tell you how to do what you ask, and assume that you have good reasons for this, how you do it. I'll do it in Python, suppose you have a connection to Redis named r , some list called some_list and some new item to add: new_item :

 lst = r.lrange(list_name, -float('Inf'), float('Inf')) if new_item not in lst: r.rpush(list_name, new_item) 
+1
source

I ran into this problem when adding work tasks to the queue because I wanted to avoid adding a lot of duplicate tasks. It would be nice to use the Redis suite (as many have suggested), but the Redis collections do not have a "blocking pop-up window" such as BRPOPLPUSH, so they are not suitable for task queues.

So here is my slightly imperfect solution (in Python):

 def pushOnlyNewItemsToList(redis, list_name, items): """ Adds only the items that aren't already in the list. Though if run simultaneously in multiple threads, there still a tiny chance of adding duplicate items. O(n) on the size of the list.""" existing_items = set(redis.lrange(list_name,0,-1)) new_items = set(items).difference(existing_items) if new_items: redis.lpush(list_name, *new_items) 

Pay attention to the warnings in the documentation line.

If you really need to ensure that there are no duplicates, the alternative is to run LREM, LPUSH inside the Redis pipeline, as in 0xAffe's answer. This approach causes less network traffic, but has the disadvantage of reordering the list. This is probably the best general answer if you don't care about the order of the lists.

0
source

If you cannot use sets (if you want to achieve any blocking functions of the POP / PUSH list), you can use a simple script:

 script load 'local exists = false; for idx=1, redis.call("LLEN",KEYS[1]) do if (redis.call("LINDEX", KEYS[1], idx) == ARGV[1]) then exists = true; break; end end; if (not exists) then redis.call("RPUSH", KEYS[1], ARGV[1]) end; return not exists or 0' 

This will return the SHA code for the script you added.

Just call then:

 evalsha 3e31bb17571f819bea95ca5eb5747a373c575ad9 1 test-list myval 

Where

  • 3e31bb17571f819bea95ca5eb5747a373c575ad9 (SHA code of the script you added)
  • 1 - number of parameters (1 for this function constantly)
  • test-list is the name of your list
  • myval - value to be added

it returns 1 if a new item was added, or 0 if it was already in the list.

0
source

Source: https://habr.com/ru/post/1481505/


All Articles