Уникальное значение в списке/наборе redis
Я хочу создать список существующих продуктов в redis
, но я хочу проверить, существует ли имя продукта уже (двойная проверка).
Мой список в настоящее время принимает дубликаты, поэтому: Может ли кто-нибудь помочь мне показать, как добавить уникальное значение в список?
Ответы
Ответ 1
Вместо использования списка используйте набор. Установки - это контейнеры для уникальных объектов. Каждый объект может отображаться только один раз в наборе. Взгляните на команды, связанные с набором: http://redis.io/commands/#set.
И пример использования redis-cli (мы пытаемся добавить "Продукт один" дважды, но он появляется только один раз в списке продуктов):
$ redis-cli
127.0.0.1:6379> sadd products "Product One"
(integer) 1
127.0.0.1:6379> sadd products "Product Two"
(integer) 1
127.0.0.1:6379> sadd products "Product Three"
(integer) 1
127.0.0.1:6379> sadd products "Product One"
(integer) 0
127.0.0.1:6379> smembers products
1) "Product Three"
2) "Product One"
3) "Product Two"
127.0.0.1:6379>
Ответ 2
Это мое (безрассудное) решение, чтобы сохранить Redis List уникальным.
(реализация в Ruby)
def push_item_to_the_list(LIST_KEY, item)
insert_status = Redis.linsert(LIST_KEY, 'before', item, item)
if insert_status == -1
Redis.lpush(LIST_KEY, item)
else
Redis.lrem(LIST_KEY, 1, item)
end
end
Каждый раз, когда вы хотите нажимать или вставлять элемент в свой список, проверьте, сможет ли команда LINSERT
поместить этот элемент сразу после одного и того же элемента (это единственный способ узнать, является ли этот элемент уже в списке redis или нет).
Если LINSERT
вернет статус -1, это означает, что он не смог найти элемент в вашем списке - все в порядке (вы можете нажать его или вставить сейчас).
Если LINSERT
вернет другое значение (размер списка в другом случае) - это значит, что он смог найти элемент уже, и он смог вставить другой элемент сразу после предыдущего. Это означает, что у вас есть (как минимум) дублирование вашего элемента. Теперь вы можете удалить один из них.
Ответ 3
Почему бы просто не позвонить Redis.lrem
раньше? Поэтому, если он обнаружит какие-либо вхождения предмета, удалит их, иначе ничего не будет делать. Примерно так:
def push_item_to_the_list(LIST_KEY, item)
Redis.lrem(LIST_KEY, 0, item)
Redis.lpush(LIST_KEY, item)
end
Ответ 4
Если вам нужно поддерживать порядок и уникальность, вы можете использовать отсортированный набор
127.0.0.1:6379> zadd products 1 "Product One"
(integer) 1
127.0.0.1:6379> zadd products 2 "Product Two"
(integer) 1
127.0.0.1:6379> zadd products 3 "Product Tree"
(integer) 1
127.0.0.1:6379> zadd products 4 "Product Four"
(integer) 1
127.0.0.1:6379> zrange products 0 -1
1) "Product One"
2) "Product Two"
3) "Product Tree"
4) "Product Four"
Ответ 5
Я предлагаю вариант, который создает уникальный список, элементы которого не теряют своей позиции. Эта опция работает намного быстрее, чем lpush, lrem, rpop. В то же время он поддерживает функционал sadd, spop.
Пример кода PHP:
public function addJobs(array $jobs): int
{
foreach ($jobs as $key => $job) {
$hash = hash('md4', $job);
if (0 === $this->client->hsetnx('QUEUE-HASHES', $hash, 1)) {
unset($jobs[$key]);
}
}
return $this->client->rpush('QUEUE', $jobs);
}
public function popJobs(int $count): array
{
if ($count < 1) {
throw new \InvalidArgumentException('Jobs count must be greater than zero');
}
$index = $count - 1;
$jobs = $this->client->lrange('QUEUE', 0, $index);
if (\count($jobs)) {
$this->client->ltrim('QUEUE', $count, -1);
$hashes = [];
foreach ($jobs as $job) {
$hashes[] = hash('md4', $job);
}
$this->client->hdel('QUEUE-HASHES', $hashes);
}
return $jobs;
}