J'ai besoin de faire correspondre les prospects froids à une base de données de nos clients. Les prospects proviennent d'un fournisseur tiers en masse (des milliers d'enregistrements) et les ventes nous demandent (selon leurs propres termes) de "filtrer nos clients" afin qu'ils n'essaient pas de vendre notre service à un client établi .Existe-t-il un moyen de filtrer un jeu de requête django basé sur la similarité de chaîne (à la python difflib)?
Évidemment, il y a des fautes d'orthographe dans les fils. Charles devient Charlie, Joseph devient Joe, etc. Je ne peux donc pas vraiment faire un filtre comparant lead_first_name à client_first_name, etc.
Je dois utiliser un mécanisme string similarity.
En ce moment j'utilise la belle difflib pour comparer les prénoms et les noms des prospects à une liste générée avec Client.objects.all()
. Cela fonctionne, mais en raison du nombre de clients, il a tendance à être lent.
Je sais que la plupart des bases de données sql ont des fonctions soundex et difference. Voir mon test dans la mise à jour ci-dessous - il ne fonctionne pas aussi bien que difflib.
Existe-t-il une autre solution? Y a-t-il une meilleure solution?
Edit:
Soundex, au moins dans ma db, ne se comporte pas aussi bien que difflib.
Voici un test simple - chercher "Joe Lopes" dans une table contenant "Joseph Lopes":
with temp (first_name, last_name) as (
select 'Joseph', 'Lopes'
union
select 'Joe', 'Satriani'
union
select 'CZ', 'Lopes'
union
select 'Blah', 'Lopes'
union
select 'Antonio', 'Lopes'
union
select 'Carlos', 'Lopes'
)
select first_name, last_name
from temp
where difference(first_name+' '+last_name, 'Joe Lopes') >= 3
order by difference(first_name+' '+last_name, 'Joe Lopes')
Les rendements ci-dessus "Joe Satriani" comme le seul match. Même en réduisant le seuil de similarité à 2, on ne retrouve pas "Joseph Lopes" en tant que correspondance potentielle.
Mais difflib fait un travail beaucoup mieux:
difflib.get_close_matches('Joe Lopes', ['Joseph Lopes', 'Joe Satriani', 'CZ Lopes', 'Blah Lopes', 'Antonio Lopes', 'Carlos Lopes'])
['Joseph Lopes', 'CZ Lopes', 'Carlos Lopes']
Modifier après la réponse gruszczy:
Avant d'écrire mon propre, je regardais et found a T-SQL implementation of Levenshtein Distance in the repository of all knowledge.
En testant, il reste ne fera pas un meilleur travail de comparaison que difflib.
Ce qui m'a conduit à rechercher quel algorithme est derrière difflib. Il semble être un modified version de l'algorithme Ratcliff-Obershelp. Malheureusement, je n'arrive pas à trouver quelqu'un d'autre qui ait déjà créé une implémentation T-SQL basée sur difflib ... Je vais essayer quand je le pourrai.
Si personne d'autre ne trouve une meilleure réponse dans les prochains jours, je l'accorderai à gruszczy. Merci, gentil monsieur.
je faisais face à une situation similaire dans un de mes projets. Nous avons généré et stocké des valeurs soundex personnalisées au lieu de compter sur le soundex intégré. Cela a quelque peu amélioré les matchs. Mais comme le dit Gruszczy, cela ne peut être résolu par soundex seul. –
Une fonction db est une bonne idée. Mais Levenshtein n'est pas aussi bon que difflib - voir ma mise à jour ci-dessus. – cethegeek
Ne pouvez-vous pas définir une plus grande distance pour la fonction levenshtein? Plus il est grand, plus il produira de résultats. – gruszczy