web-dev-qa-db-fra.com

Cassandra Recherche en texte intégral

Recherche en texte intégral à Cassandra;

Je suis assez nouvelle pour Cassandra et souhaite mieux la comprendre. J'essaie d'effectuer une recherche en texte intégral à Cassandra, mais après quelques recherches, j'ai constaté qu'il peut ne constitue pas une approche "simple" pour cela .. et je dis peut-être parce que la première page de Google n'a pas dit grand chose de rien.

J'essaie donc de comprendre maintenant quelle est la meilleure approche à suivre ici. Cela m’amène à formuler mes propres hypothèses sur la base de ce que j’ai appris jusqu’à présent sur Cassandra, qui repose sur ces deux principes; a) concevez vos tables en fonction de vos requêtes, plutôt que des données, et b) plus de données est une bonne chose, à condition que vous l'utilisiez correctement.

Cela dit, j’ai proposé quelques solutions que je voudrais partager et je demande également à ceux qui ont une meilleure idée de bien vouloir me mettre au courant avant de m’engager dans des activités déraisonnables/naïves.

Première solution: créez une famille de colonnes (CF), avec deux clés primaires et un index, comme suit:

CREATE TABLE "FullTextSearch" (
"PartialText" text,
"TargetIdentifier" uuid,
"CompleteText" text,
"Type" int,
PRIMARY KEY ("PartialText","TargetIdentifier")
);
CREATE INDEX IX_FullTextSearch_Type "keyspace"."FullTextSearch" ("Type");

Avec le tableau ci-dessus, il faudrait insérer des lignes pour le texte "Hello World" comme suit:

BATCH APPLY;
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("H",000000000-0000-0000-0000-000000000,"Hello World",1);
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("He",000000000-0000-0000-0000-000000000,"Hello World",1);
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("Hel",000000000-0000-0000-0000-000000000,"Hello World",1);
.....
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("Hello Wor",000000000-0000-0000-0000-000000000,"Hello World",1);
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("Hello Worl",000000000-0000-0000-0000-000000000,"Hello World",1);
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("Hello World",000000000-0000-0000-0000-000000000,"Hello World",1);
.....
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("Wor",000000000-0000-0000-0000-000000000,"Hello World",1);
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("Worl",000000000-0000-0000-0000-000000000,"Hello World",1);
INSERT INTO "FullTextSearch" ("PartialText","TargetIdentifier","CompleteText","Type") VALUES ("World",000000000-0000-0000-0000-000000000,"Hello World",1);
END BATCH;

Fondamentalement, ce qui précède satisfait les caractères génériques/texte partiel suivants "% o W%", "Hello%", "Worl%"; Cependant, il ne satisfera pas les mots partiels tels que "% ell%" pour "Bonjour", ce que je peux sentir d'accord pour le moment ..... (OCD sorta ici)

Cette approche est un peu pénible pour moi parce que je devrais maintenant supprimer/réinsérer chaque fois qu'un changement de sauvegarde/nom survient sur le "TargetIdentifier";

La deuxième solution serait très similaire seulement cette fois en utilisant des colonnes larges; où la table pourrait ressembler à:

CREATE TABLE "FullTextSearch" (
"TargetIdentifier" uuid,
"Type" int,
"CompleteText" text,
PRIMARY KEY("TargetIdentifier")
);

et maintenant, pendant une recherche, quelque chose comme:

SELECT * FROM "FullTextSearch" WHERE "He" = 1;

de sorte que si la colonne existe, les lignes respectives sont retournées;

Troisième solution: semblable à celle ci-dessus, mais cette fois, au lieu d'utiliser des colonnes larges, nous utilisons une colonne définie telle que map pour les textes partiels, et effectuons une requête du type:

SELECT * FROM "FullTextSearch" WHERE "PartialTexts"['He'] = 1;

En tout cas, je suis à court d'idées, il est tard et je ne peux qu'espérer une bonne réponse! S'il vous plaît, laissez-moi savoir ce que je devrais faire ici ... suis-je même sur le bon chemin?

12
user1953264

AFAIK Datastax Enterprise Search est le successeur (commercial) de Solandra.

Cassandra 2.0 prend en charge les "index secondaires personnalisés". Les index secondaires personnalisés sont du code Java. Votre propre implémentation doit implémenter la classe abstraite org.Apache.cassandra.db.index.SecondaryIndex (voir http://www.datastax.com/documentation/cql/3.1/cql/cql_reference/create_index_r.html )

Je ne sais pas s'il existe des implémentations pour Elasticsearch ou Solr.

Je ne recommanderais pas de coder toute la logique étrange de la recherche en texte intégral, telle que l’acquisition de racines, la prise en charge de langues multiples/exotiques ou même d’autres éléments géographiques.

Mais SecondaryIndex serait un bon point pour commencer à intégrer votre moteur de recherche préféré.

8
Robert Stupp

Si votre ensemble de données est relativement petit, vous pouvez simplement utiliser une instance en mémoire de lucene, mettre à jour l'index à un intervalle défini et vous êtes prêt à commencer.

1
TinusSky

Départ SOLANDRA (ancien Lucandra)

Mais je pense que Solandra n’est plus activement développé, l’auteur s’est installé à Datastax et y a poursuivi son travail.

Vous pouvez également consulter Datastax Enterprise Search

Il y a aussi quelques limitations, regardez DistributedSearch

0
Jignesh Dhua

La chose la plus élémentaire à propos de cassandra est que si vous voulez utiliser la clause where pour le filtrage des enregistrements, cette colonne est la clé primaire ou vous devez lui attribuer un index. Ce que je peux voir, c'est que vous avez donné la clé primaire au champ "TargetIdentifier" et index to "Type" et utilisation de "CompleteText" dans la clause where afin que cela ne fonctionne pas.

Attribuez un index secondaire à "CompleteTex" et vérifiez si vous obtenez le résultat souhaité ou non.

0
Working Hard..

Quelques autres options que vous avez: Stratio Lucene Plugin . Cela utilise Lucene pour l'implémentation d'un index secondaire natif.

Vous disposez également de Index secondaire attaché SSTable (SASI) disponible pour une recherche en texte libre.

Sachez que ces deux stratégies utilisent des index distribués localement, de sorte que les requêtes ne seront pas très performantes, car les recherches finiront par être diffusées sur l'ensemble du cluster. Pour SASI, vous pouvez éviter cela si vous pouvez utiliser une clé de partition dans le cadre de votre requête.

0
Jason White