Ho gli hash compositi spamsum per circa dieci milioni di file in una tabella di database e mi piacerebbe trovare i file che sono ragionevolmente simili tra loro. hash Spamsum sono composti da due hash CTPH di massimo 64 byte e sembrano in questo modo:Il modo migliore per cercare milioni di hash sfocati
384:w2mhnFnJF47jDnunEk3SlbJJ+SGfOypAYJwsn3gdqymefD4kkAGxqCfOTPi0ND:wemfOGxqCfOTPi0ND
Essi possono essere suddivisi in tre sezioni (dividere la stringa sui due punti): dimensioni
- Block :
384
nell'hash sopra - Prima firma:
w2mhnFnJF47jDnunEk3SlbJJ+SGfOypAYJwsn3gdqymefD4kkAGxqCfOTPi0ND
- seconda firma:
wemfOGxqCfOTPi0ND
La dimensione del blocco si riferisce alla dimensione del blocco per la prima firma e la dimensione del blocco per la seconda firma è doppia rispetto a quella della prima firma (qui: 384 x 2 = 768). Ogni file ha uno di questi hash compositi, il che significa che ogni file ha due firme con blocchi di dimensioni diverse.
Le firme dello spamsum possono essere confrontate solo se corrispondono alle dimensioni dei blocchi. Ciò significa che l'hash composito sopra può essere paragonato a qualsiasi altro hash composito che contiene una firma con una dimensione di blocco di 384 o 768. La somiglianza delle stringhe di firma per gli hash con dimensioni di blocco simili può essere presa come misura della somiglianza tra i file rappresentati dagli hash.
Quindi, se abbiamo:
file1.blk2 = 768
file1.sig2 = wemfOGxqCfOTPi0ND
file2.blk1 = 768
file2.sig1 = LsmfOGxqCfOTPi0ND
possiamo ottenere un senso del grado di somiglianza tra i due file calcolando qualche distanza di modifica ponderata (come la distanza di Levenshtein) per t lui due firme. Qui i due file sembrano essere abbastanza simili.
leven_dist(file1.sig2, file2.sig1) = 2
Si può anche calcolare un punteggio di somiglianza normalizzato tra i due hash (vedi i dettagli here).
Mi piacerebbe trovare due file più simili al 70% in base a questi hash e ho una forte preferenza per l'utilizzo dei pacchetti software disponibili (o API/SDK), anche se non ho paura della codifica la mia strada attraverso il problema.
Ho provato a rompere gli hash e indicizzarli con Lucene (4.7.0), ma la ricerca sembra essere lenta e noiosa. Ecco un esempio delle domande Lucene che ho provato (per ogni firma singola - due volte al cancelletto e utilizzando il KeywordAnalyzer maiuscole e minuscole):
(blk1:768 AND sig1:wemfOGxqCfOTPi0ND~0.7) OR (blk2:768 AND sig2:wemfOGxqCfOTPi0ND~0.7)
Sembra che Lucene di incredibly fast Levenshtein automata non accetta limiti modificare a distanza di cui sopra 2 (Ne ho bisogno per supportare fino a 0,7 x 64 ≃ 19) e che il suo normale algoritmo di distanza di modifica non è ottimizzato per lunghi termini di ricerca (the brute force method used does not cut off calculation once the distance limit is reached). Detto questo, può darsi che la mia query non sia ottimizzata per quello che voglio fare quindi non esitate a correggermi su questo.
Mi chiedo se posso realizzare ciò di cui ho bisogno utilizzando uno degli algoritmi offerti da Lucene, invece di calcolare direttamente la distanza di modifica. Ho sentito che gli alberi BK sono il modo migliore per indicizzare tali ricerche, ma non conosco le implementazioni disponibili dell'algoritmo (Lucene li usa del tutto?). Ho anche sentito che una soluzione probabile è quella di restringere la lista di ricerca usando i metodi n-grammi, ma non sono sicuro di come si possa confrontare il calcolo della distanza in termini di inclusività e velocità (sono sicuro che Lucene lo supporta). E a proposito, c'è un modo per far eseguire a Lucene una ricerca per termine in modalità parallela?
Dato che sto usando Lucene solo per pre-abbinare gli hash e che calcolo il punteggio di somiglianza reale utilizzando l'algoritmo appropriato più avanti, ho solo bisogno di un metodo che sia almeno inclusivo come la distanza di Levenshtein usata nel calcolo del punteggio di somiglianza - cioè, non voglio che il metodo di pre-abbinamento escluda gli hash che verrebbero contrassegnati come corrispondenze dall'algoritmo di punteggio.
Qualsiasi aiuto/teoria/riferimento/codice o indizio per iniziare è apprezzato.