文档首页/ 云数据库 GeminiDB/ GeminiDB Redis接口/ 常见问题/ 数据库使用/ scan指定match参数,数据中确实存在匹配的key,为什么返回的是空
更新时间:2024-08-01 GMT+08:00
分享

scan指定match参数,数据中确实存在匹配的key,为什么返回的是空

问题描述

如下图所示,数据库中存在key为test的数据,用scan match的方式却没有返回这个数据。

139.9.177.148:8635> scan 1 match tes*
1) "21"
2) (empty list or set)
139.9.177.148:8635> get test
"abc"
139.9.177.148:8635>scan 0 match tes*
1) "21"
2) (empty list or set)
139.9.177.148:8635>

问题分析

MATCH选项让命令只返回和给定模式相匹配的元素, 对元素的模式匹配工作是在命令从数据集中取出元素之后, 向客户端返回元素之前的这段时间内进行的, 如果取出的元素都和模式不匹配,则不会返回任何元素。

解决方案

多次scan,以返回的游标值是否为0作为全遍历结束的标记,每次scan时使用上次scan返回的游标值。

相关知识

  • SCAN命令的基本用法

    SCAN cursor [MATCH pattern] [COUNT count]

    SCAN命令是一个基于游标的迭代器(cursor based iterator)。SCAN命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN命令的游标参数, 以此来延续之前的迭代过程。

    当SCAN命令的游标参数被设置为0时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为0的游标时, 表示迭代已结束。

    redis 127.0.0.1:6379> scan 0 
    1) "17" 
    2) 1) "key:12"
       2) "key:8"
       3) "key:4"
       4) "key:14"
       5) "key:16"
       6) "key:17"
       7) "key:15"
       8) "key:10"
       9) "key:3"
       10) "key:7"
       11) "key:1"
    redis 127.0.0.1:6379> scan 17 
    1) "0"
    2) 1) "key:5" 
       2) "key:18"
       3) "key:0"
       4) "key:2"
       5) "key:19"
       6) "key:13"
       7) "key:6"
       8) "key:9"
       9) "key:11"

    在上面这个例子中, 第一次迭代使用0作为游标, 表示开始一次新的迭代。

    第二次迭代使用的是第一次迭代时返回的游标, 即命令回复第一个元素的值 :17 。

    从上面的示例可以看到, SCAN命令的回复是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素。

    在第二次调用SCAN命令时, 命令返回了游标0 , 这表示迭代已经结束, 整个数据集(collection)已经被完整遍历过了。

    以0作为游标开始一次新的迭代, 一直调用SCAN命令, 直到命令返回游标0, 我们称这个过程为一次完整遍历(full iteration)。

  • COUNT选项

    虽然增量式迭代命令不保证每次迭代所返回的元素数量, 但我们可以使用COUNT选项, 对命令的行为进行一定程度上的调整。

    基本上,COUNT选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。 COUNT参数的默认值为10。

    并非每次迭代都要使用相同的COUNT值。

    用户可以在每次迭代中按自己的需要随意改变COUNT值, 只要记得将上次迭代返回的游标用到下次迭代里面。

  • MATCH选项

    MATCH选项让命令只返回和给定模式相匹配的元素,以下是一个使用MATCH选项进行迭代的示例。

    redis 127.0.0.1:6379> mset foo a foobar b feelsgood c bar d (integer) 4
    redis 127.0.0.1:6379> scan 0 match f*
     1) "0"
     2) 1) "foo"
        2) "feelsgood"
        3) "foobar"

    需要注意的是, 对元素的模式匹配工作是在命令从数据集中取出元素之后, 向客户端返回元素之前的这段时间内进行的, 所以如果被迭代的数据集中只有少量元素和模式相匹配, 那么迭代命令或许会在多次执行中都不返回任何元素。

    以下是这种情况的一个例子。

    redis 127.0.0.1:6379> scan 0 MATCH *11*
     1) "288"
     2) 1) "key:911"
    redis 127.0.0.1:6379> scan 288 MATCH *11*
     1) "224"
     2) (empty list or set)
    redis 127.0.0.1:6379> scan 176 MATCH *11* COUNT 1000
     1) "0"
     2)  1) "key:611"
         2) "key:711" 
         3) "key:118" 
         4) "key:117"
         5) "key:311"
         6) "key:112" 
         7) "key:111" 
         8) "key:110" 
         9) "key:113"
         10) "key:211"
         11) "key:411"
         12) "key:115"
         13) "key:116"
         14) "key:114"
         15) "key:119"
         16) "key:811"
         17) "key:511"
         18) "key:11"

    以上的大部分迭代都不返回任何元素。 在最后一次迭代, 我们通过将COUNT选项的参数设置为1000 , 强制命令为本次迭代扫描更多元素, 从而使得命令返回的元素也变多了。

相关文档