سؤال

كيف يمكنني تنفيذ الإكمال التلقائي باستخدام redis؟

قل على سبيل المثال لدي صفيف ["alfred","joel","jeff","addick"]. عندما أكتب a انا حصلت ["alfred", "addick"]

آمل أن تحصل على هذه النقطة. كيف يمكنني تنفيذ هذا باستخدام أوامر redis بكفاءة (إن أمكن ولكن أعتقد أنه). سيكون من الرائع أن أحصل على بعض الأوامر البسيطة التي يمكنني تجربتها عبر Telnet لتقليد هذا السلوك.

شكرًا

ملاحظة: Merry X-Mas لكم جميعًا :)

هل كانت مفيدة؟

المحلول

إذا كنت تتعامل مع مجموعة بيانات كبيرة ، فإنني أقترح النظر في تنفيذ هذا باعتباره trie. لقد ألقيت معًا جزءًا صغيرًا من الياقوت من شأنه أن يفعل هذا:

require 'rubygems'
require 'redis'

class RedisTrie
  TERMINAL = '+'

  def initialize(prefix)
    @prefix = prefix
    @r = Redis.new
  end

  def add_word(word)
    w = word.gsub(/[^a-zA-Z0-9_-]/, '')
    key = "#{@prefix}:"

    w.each_char do |c|
      @r.zset_add key, c.bytes.first, c
      key += c
    end

    @r.zset_add key, 0, TERMINAL
  end

  def add_words(*words)
    words.flatten.compact.each {|word| add_word word}
  end

  def suggest(text)
    @r.zset_range("#{@prefix}:#{text}", 0, -1).map do |c|
      (c == TERMINAL) ? text : suggest(text + c)
    end.flatten
  end
end

rt = RedisTrie.new('trie')

rt.add_words %w( apple automobile carwash oil-change cranky five ruthie axe auto )

p rt.suggest(ARGV.shift.to_s)

علي سبيل المثال:

$ ruby RedisTrie.rb
["apple", "auto", "automobile", "axe", "carwash", "cranky", "five", "oil-change", "ruthie"]
$ ruby RedisTrie.rb a
["apple", "auto", "automobile", "axe"]
$ ruby RedisTrie.rb au
["auto", "automobile"]
$ ruby RedisTrie.rb aux
[]

اقرأ المزيد عن المحاولات في دخول ويكيبيديا على المحاولات.

ستحتاج بالتأكيد إلى تحسين طريقة اقتراحك لعدم إرجاع جميع القيم ، بدلاً من ذلك فقط إرجاع قيم X الأولى التي يجدها. سوف يهزم الغرض لتكرار بنية البيانات بأكملها.

نصائح أخرى

نعم ، بعد عامين من نشر السؤال ، ولكن مع ذلك ذات صلة

على موقع Redis ، يوجد برنامج تعليمي كامل (في Ruby):

تلقائي مع redis

لقد وجدت أيضًا هذا المقتطف عند قراءة Simon Willison المثيرة للإعجاب ريديس البرنامج التعليمي.

المحلول:

مرحبا ماكس،

Keys ليس هو الطريق للذهاب ، أفضل شيء يمكنك القيام به هو استخدام مجموعة مصنفة بدلاً من ذلك. ما تريده هو تحويل أول 4 أو 5 أحرف من الأوتار إلى عدد صحيح (يمكنك أن تتخيل كل Char كرقم من رقم Radix 256 على سبيل المثال ، ولكن هناك تمثيل أفضل) وإضافة جميع أسماء المستخدمين إلى مجموعة مصنفة .

ثم باستخدام ZrangeByScore ، يمكنك الحصول على جميع العناصر بين نطاق معين.

هذه الطريقة أكثر قابلية للتطوير لأنها شيء O (log (n)).

أنا أغطي هذه الأشياء في كتاب Redis المتطور ببطء شديد ...

هتافات ، سلفاتور

إليك خوارزمية بسيطة ميتة في PHP للإكمال التلقائي الأبجدي مع redis:

function getNextChar($char) {
    $char++;
    if(strlen($char) > 1) { $char--; }
    return $char;
}

function createDictionary($redis, $key, $wordList) {
    if(!$redis->exists($key)) {
        foreach($wordList as $word) {
            $redis->zadd($key, 0, $word);
        }
    }
}

function getLexicalAutocomplete($redis, $dictionaryKey, $input) {
    $inputNext = substr($input, 0, -1) . getNextChar(substr($input, -1)); //ab -> ac

    $redis->zadd($dictionaryKey, 0, $input);
    $redis->zadd($dictionaryKey, 0, $inputNext);

    $rangeStart = $redis->zrank($dictionaryKey, $input)+1;
    $rangeEnd = $redis->zrank($dictionaryKey, $inputNext)-1;

    $autocompleteResults = $redis->zrange($dictionaryKey, $rangeStart, $rangeEnd);

    $redis->zrem($dictionaryKey, $input);
    $redis->zrem($dictionaryKey, $inputNext);

    return $autocompleteResults;
}

$redis = new Redis();
$redis->connect('', 0); //Your redis server ip/port goes here

createDictionary($redis, "dict", array("alfred", "joel", "jeff", "addick"));
$result = getLexicalAutocomplete($redis, "dict", $argv[1]);

echo json_encode($result);

بناء على المقال تلقائي مع redis بواسطة Salvatore ، باستثناء أنني حاجة إلى توليد قاموس الإكمال التلقائي إضافي ، على حساب القليل من عقوبة الأداء (اثنين من Zadds و Zrems إضافية) ولكن في معظم الحالات يجب أن يكون أداءها جيدًا. يفترض البرنامج النصي phpredis ، لكن يجب أن يكون هو نفسه مع Predis.

أمثلة الإخراج:

> php redisauto.php a
["addick","alfred"]

> php redisauto.php ad
["addick"]

> php redisauto.php al
["alfred"]

> php redisauto.php j
["jeff","joel"]

> php redisauto.php je
["jeff"]

فيما يلي ميناء من تطبيق Ruby الأصلي لـ Antirez في Python:

http://www.varunpant.com/posts/auto-complete-with-redis-python

لقد مررت للتو بوضع رائع يخدم المشكلة الدقيقة التي تتحدث عنها ، وأكثر من ذلك. تحقق من ذلك

ربما لا علاقة لها ، ولكن إذا هبطت هنا ، فقد تكون مهتمًا أيضًا بالطريقة السهلة والسهلة والسريعة والقابلة للتطوير لإكمال حقول واجهة المستخدم التلقائية مع اقتراحات:

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/suggesters-completion.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top