J'ai un nombre raisonnable de nœuds (environ 60 000)
(:Document {title:"A title"})
Étant donné un titre, je veux trouver le nœud correspondant, s'il existe. Le problème est que le titre que je suis donné n'est pas cohérent. C'est-à-dire que parfois le début d'un nouveau mot est Capital, parfois tout est minuscule. Parfois, les mots-clés sont combinés avec la casse Kebab, parfois ils sont écrits normalement en tant que mots clés.
Pour compenser cela, j'utilise apoc et la distance de Levenshtein entre le titre donné et chaque nœud et n'accepte qu'un nœud comme correspondance s'il est inférieur à un seuil:
MATCH (a:Document)
WHERE apoc.text.distance(a.title, "A title") < 10
RETURN a
Cette ne s'adapte pas bien. Actuellement, une seule recherche prend environ 700 ms , ce qui est trop lent, étant donné qu’elle atteindra probablement environ 150 000 nœuds.
Je pensais stocker/mettre en cache l'occurrence de titres alternatifs dans une propriété alias:[...]
du nœud et construire un index sur tous les alias, mais je ne sais pas si cela est possible dans Neo4j.
Quel est le moyen le plus rapide de "trouver fuzzy" un titre à partir d’une grande base de données de noeuds?
Dans Neo4j 3.5 (actuellement en version beta03), il existe des fonctionnalités FTS (Full-Text Search).
EDIT: J'ai écrit un article de blog détaillé sur FTS dans Neo4j: https://graphaware.com/neo4j/2019/01/11/neo4j-full-text-search-deep-dive.html
Vous pouvez ensuite interroger vos documents à l’aide de la syntaxe Lucene Classic Query Parser .
Créer l'index:
CALL db.index.fulltext.createNodeIndex('documents', ['Document'], ['title','text'])
Importer des documents:
LOAD CSV WITH HEADERS FROM "file:///docs.csv" AS row
CREATE (n:Document) SET n = row
Interroger les documents dont le titre contient "lourd péage"
CALL db.index.fulltext.queryNodes('documents', 'title: "heavy toll"')
YIELD node, score
RETURN node.title, score
╒══════════════════════════════════════════════════════════════════════╤══════════════════╕
│"node.title" │"score" │
╞══════════════════════════════════════════════════════════════════════╪══════════════════╡
│"Among Deaths in 2016, a Heavy Toll in Pop Music - The New York Times"│3.7325966358184814│
└──────────────────────────────────────────────────────────────────────┴──────────────────┘
Requête pour le même titre avec une faute de frappe:
CALL db.index.fulltext.queryNodes('documents', 'title: \\"heavy~ tall~\\"')
YIELD node, score
RETURN node.title, score
Notez que les guillemets sont échappés =>\", la chaîne transmise à l’analyseur sous-jacent doit contenir les guillemets afin d’effectuer une requête syntaxique au lieu d’une requête booléenne.
De plus, la variable tidle
à côté des termes indique qu'il est nécessaire d'effectuer une recherche floue à l'aide de l'algorithme Damarau-Levenshtein.
╒══════════════════════════════════════════════════════════════════════╤═════════════════════╕
│"node.title" │"score" │
╞══════════════════════════════════════════════════════════════════════╪═════════════════════╡
│"Among Deaths in 2016, a Heavy Toll in Pop Music - The New York Times"│0.868073046207428 │
├──────────────────────────────────────────────────────────────────────┼─────────────────────┤
│"Prisons Run by C.E.O.s? Privatization Under Trump Could Carry a Heavy│0.4014900326728821 │
│ Price - The New York Times" │ │
├──────────────────────────────────────────────────────────────────────┼─────────────────────┤
│"‘All Talk,’ ‘No Action,’ Says Trump in Twitter Attack on Civil Rights│0.28181418776512146 │
│ Icon - The New York Times" │ │
├──────────────────────────────────────────────────────────────────────┼─────────────────────┤
│"Immigrants Head to Washington to Rally While Obama Is Still There - T│0.24634429812431335 │
│he New York Times" │ │
├──────────────────────────────────────────────────────────────────────┼─────────────────────┤
L'indexation, comme indiqué dans la answer de Christophe Willemsen, est indispensable pour accélérer les recherches, mais j'aimerais également indiquer une autre fonction historique qui pourrait mieux correspondre à votre "recherche floue":
Soundex est un algorithme phonétique permettant d'indexer des noms par son, tel que prononcé en anglais.