Domanda

Come posso implementare un completamento automatico utilizzando Redis?

Diciamo per esempio ho un ["alfred","joel","jeff","addick"] array. Quando digito a ricevo ["alfred", "addick"]

Spero che si ottiene il punto. Come posso implementare questo utilizzando Redis comandi in modo efficiente (se possibile, ma penso che sia). Sarebbe bello se potessi ottenere alcuni semplici comandi posso provare via telnet di imitare questo comportamento.

Grazie

P.S: Merry X-mas a tutti voi:)

È stato utile?

Soluzione

Se hai a che fare con un grande insieme di dati, vorrei suggerire di considerare l'attuazione del presente come un trie. Ho gettato insieme un po 'piccolo di Ruby che farebbe questo:

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)

Ad esempio:

$ 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
[]

Per saperne di più sul Tentativi a ingresso di Wikipedia su Tentativi .

Sarà sicuramente voglia di ottimizzare il metodo per suggerire non restituire tutti i valori, invece solo la restituzione di valori del primo X che trova. Sarebbe vanificato l'obiettivo di iterare l'intera struttura dei dati.

Altri suggerimenti

[Sì, 2 anni dopo la questione è stata inviata, ma comunque rilevanti]

Sul sito Redis, c'è un tutorial completo (in Ruby):

  

Auto Completo di Redis

Ho trovato anche questo frammento durante la lettura impressionante Redis esercitazione .

Soluzione:

  

Ciao Max,

     

CHIAVI non è la strada da percorrere, il migliore   cosa che puoi fare è quello di utilizzare invece un   set ordinato. Ciò che si vuole è quello di trasformare   i primi 4 o 5 caratteri del   stringhe in un numero intero (si può   immaginare ogni char come cifra di una   radix 256 numero per esempio, ma   ci sono una migliore rappresentazione) e   aggiungere tutti i vostri nomi utente in un ordinato   set.

     

Quindi, utilizzando ZRANGEBYSCORE si può ottenere   tutti gli elementi tra un determinato   gamma.

     

Questo metodo è molto più scalabile   è una cosa O (log (N)).

     

sto coprendo questa roba nel mio molto   lenta evoluzione Redis libro ...

     

Saluti, Salvatore

Ecco un semplice algoritmo di morti in PHP per il completamento automatico alfabetico con 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);

In base all'articolo completamento automatico con Redis di Salvatore, tranne che Hax la necessità di generare un dizionario di completamento automatico in più, a scapito di un piccolo po 'di pena di prestazioni (un paio di zadds e zrems in più), ma nella maggior parte dei casi dovrebbe funzionare bene. Lo script assume phpredis, ma dovrebbe in pratica essere lo stesso con Predis.

Esempi di output:

> 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"]

Qui è un porto di implementazione Ruby antirez originale in Python:

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

Ho appena passato attraverso un posto impressionante che servono l'esatto problema si sta parlando, e altro ancora. Controllare fuori

Probabilmente non collegati, ma se è atterrato qui, si potrebbe anche essere interessato al modo semplice, corretta, veloce e scalabile per completare automaticamente i campi di interfaccia utente con suggerimenti:

http: //www.elasticsearch. org / guide / it / elasticsearch / riferimento / corrente / search-suggesters-completion.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top