【问题标题】:Unique value in redis list/setredis 列表/集合中的唯一值
【发布时间】:2014-12-11 07:57:36
【问题描述】:

我想在redis 中列出现有产品,但我想先检查产品名称是否已经存在(重复检查)。

我的列表目前接受重复项,所以:谁能帮我展示如何在列表中添加唯一值?

【问题讨论】:

    标签: redis nosql


    【解决方案1】:

    redis 5 ZPOPMIN https://redis.io/commands/zpopmin 删除并返回存储在 key 的排序集中得分最低的 count 个成员。

    当未指定时,count 的默认值为 1。指定大于排序集基数的计数值不会产生错误。返回多个元素时,得分最低的将是第一个,其次是得分较高的元素。

    【讨论】:

      【解决方案2】:

      我提出了一个创建唯一列表的选项,其中的元素不会丢失其位置。此选项的工作速度比 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;
      }
      

      【讨论】:

        【解决方案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】:

        这是我保持 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
        

        每次当你想pushinsert到你的列表时,检查LINSERT命令是否能够把这个项目放在同一个项目之后(这是我知道检查项目是否已经在 redis 列表中的唯一方法。

        如果LINSERT 将返回状态 -1,则表示它无法在您的列表中找到项目 - 一切正常(您现在可以推送或插入)。

        如果LINSERT 将返回其他值(在其他情况下为列表大小) - 这意味着它已经能够找到项目并且它能够插入另一个项目,就在前一个项目之后。这意味着您的项目有(至少一个)重复项。您现在可以删除其中一个。

        【讨论】:

          【解决方案5】:

          如果您需要保持顺序和唯一性,您可以使用排序集

          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"
          

          【讨论】:

          • 有没有办法在redis中获取一个包含唯一项目的队列?所以一个排序的集合,但我想从前面弹出一些东西,然后继续弹出。 :-)
          【解决方案6】:

          不要使用列表,而是使用集合。集合是唯一对象的容器。每个对象在一组中只能出现一次。在此处查看与 set 相关的命令: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>
          

          【讨论】:

          • ...如果您需要按顺序排列“列表” - 请使用排序集 :)
          • 我需要订单
          猜你喜欢
          • 2014-03-24
          • 1970-01-01
          • 1970-01-01
          • 2012-01-15
          • 2016-03-10
          • 1970-01-01
          • 2020-01-01
          • 2019-09-14
          • 2016-08-21
          相关资源
          最近更新 更多