Redis completamento automatico
-
21-09-2019 - |
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:)
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):
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: