redis:auto-complete

weixin_34162695發表於2018-12-02

“Redis IN Action” 這本書的中的實現思路

理論基礎,以下3篇文章:

jedis:向redis server提交bytes
redis:encoding
redis: lexicographic ordering
redis: Details on strings comparison
redis commands: zrangebylex

演算法說明:

redis in action: 6.1.2 Address book autocomplete

簡化問題, username 字元的取值範圍是 [a,z]
使用者輸入: "abc"
查詢以 “abc” 打頭的usernames

確定下限:
“abb{”

確定上限:
“abc{”

範圍在:
[ "abb{", "abc{" ]

我來解釋下:
lexical order:

abb
abba
abbb
abbc
...
abb{
abc
abca
abcb
...
abc{
abd
所以,以"abc"打頭的usernames都在 "abb{" 和 "abc{"之間。

Notes: 如果 為什麼要用 { , 可以檢視 unicode code points

繼續擴充套件範圍, 構成 username 的 字元範圍 擴充套件整個 unicode: BMP

unicode:BMP
指代unicode code points在
U+0000 to U+FFFF
範圍內的字元。

private static void autoCompleteBMP(Jedis conn, String key, String prefix) {
        if (prefix == null || prefix.isEmpty()) {
            return;
        }

        int len = prefix.length();

        //1. header tail
        String header = prefix;
        String tail = prefix;

        if (len > 1) {
            header = prefix.substring(0, len - 1);
            tail = prefix.substring(len - 1, len);
        }

        //2. min, max
        int codePoint = tail.codePointAt(0);
        String start = "\u0000";

        if (Character.isValidCodePoint(codePoint - 1)) {
            start = new String(new int[]{codePoint - 1}, 0, 1);
        }


        String min = start + "\uFFFF";
        String max = tail + "\uFFFF";

        if (len > 1) {
            min = header + start + "\uFFFF";
            max = header + tail + "\uFFFF";
        }


//        System.out.println("min: " + min + " ; " + "max: " + max);


        //3. zrangebylex
        Set<String> strings = conn.zrangeByLex(key, "(" + min, "(" + max);

        System.out.println(strings);
    }

相關文章