2 votes

Construction d'un index Examine (lucene.net) avec une liste d'identifiants séparés par des virgules

J'ai un site web Umbraco qui utilise Examine search qui est basé sur lucene.net. J'essaie de faire exactement ce qui est décrit dans l'article suivant :

Interroger une liste d'identifiants séparés par des virgules avec Examine et Lucene.Net ?

Le problème que je rencontre est lorsque j'essaie de créer l'index en utilisant le code suivant :

// Loop through articles
        foreach (var a in articles)
        {
            yield return new SimpleDataSet()
            {
                NodeDefinition = new Examine.IndexedNode()
                {
                    NodeId = a.Id,
                    Type = "Article"

                },
                RowData = new Dictionary<string, string>()
                {
                    {"Name", a.Name},
                    {"Url", a.NiceUrl},
                    {"Category", "1234"},
                    {"Category", "5678"}
                }
            };
        }

Je reçois l'erreur suivante :

Un élément avec la même clé a déjà été ajouté.

Quelqu'un sait-il comment résoudre ce problème ?

2voto

Shazwazza Points 33

La prochaine version d'Examine (v2) supportera cela correctement, avec un peu de chance, elle pourrait sortir d'ici quelques mois, mais cela dépend du temps dont nous disposons.

En attendant, vous pouvez utiliser l'événement DocumentWriting sur votre indexeur, ce qui vous donne un accès direct au document Lucene, puis vous pouvez indexer comme vous le souhaitez. Ainsi, vous pourriez initialement avoir une liste d'identifiants séparés par des virgules pour vos catégories et, au cours de cet événement, vous pourriez les diviser et les ajouter en tant que valeurs individuelles dans Lucene.

1voto

rae1 Points 4603

L'erreur que vous rencontrez est une restriction de l'application .NET Dictionary<TKey, TValue> comme mentionné par @DavidH. La restriction est héritée de la classe Examine SimpleDataSet qui, en regardant la classe source ne permet que Dictionary<string, string> comme moyen d'ajouter des données de ligne à un document.

Cependant, un fichier Lucene Document fait vous permettent d'ajouter plusieurs champs portant le même nom, comme indiqué dans la question liée :

using Lucene.Net.Documents;

var document = new Document();
document.Add(CreateField("Id", a.Id));
document.Add(CreateField("Name", a.Name));
document.Add(CreateField("Url", a.NiceUrl));        
document.Add(CreateField("Category", "1234"));    
document.Add(CreateField("Category", "5678"));    

...

private Field CreateField(string fieldName, string fieldValue)
{
    return new Field(
        fieldName, 
        fieldValue, 
        Field.Store.YES, 
        Field.Index.ANALYZED);
}

Bien qu'elle ne soit pas aussi pratique que l'API d'Examine, l'utilisation native de Lucene est beaucoup plus souple pour ces scénarios.

0voto

Haney Points 8373

Les clés du dictionnaire doivent être uniques, ce qui n'est pas spécifique à Lucene, mais plutôt au système .NET Dictionary<TKey, TValue> classe. Une option possible consiste à délimiter les valeurs sous une clé de dictionnaire "Catégorie", puis à les séparer sur le caractère "pipe" pour les analyser :

RowData = new Dictionary<string, string>()
{
    {"Name", a.Name},
    {"Url", a.NiceUrl},
    {"Category", "1234|5678"}
}

Vous pouvez alors utiliser string.Split sur le caractère '|' pour les analyser à nouveau.

0voto

miracledev Points 729

Voici un exemple complet de ce que l'on peut faire avec Lucene, mais comme on l'a dit, Examine semble limiter la flexibilité en ayant une entrée dans un dictionnaire. Cependant, il devrait être simple de modifier Examine pour qu'il puisse gérer cela.

public static void Main (string[] args)
    {
        Analyzer analyser = new StandardAnalyzer (Lucene.Net.Util.Version.LUCENE_CURRENT);
        Directory dir = new RAMDirectory ();

        using (IndexWriter iw = new IndexWriter (dir, analyser, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED)) {

            Document doc1 = new Document ();
            doc1.Add (new Field("title", "multivalued", Field.Store.YES, Field.Index.ANALYZED));
            doc1.Add (new Field("multival", "val1", Field.Store.YES, Field.Index.ANALYZED));
            doc1.Add (new Field("multival", "val2", Field.Store.YES, Field.Index.ANALYZED));
            iw.AddDocument (doc1);
            Document doc2 = new Document ();
            doc2.Add (new Field("title", "singlevalued", Field.Store.YES, Field.Index.ANALYZED));
            doc2.Add (new Field("multival", "val1", Field.Store.YES, Field.Index.ANALYZED));        
            iw.AddDocument (doc2);
        }

        using (Searcher searcher = new IndexSearcher (dir, true)) {
            var q1 = new TermQuery (new Term ("multival", "val1"));
            var q1result = searcher.Search (q1, 1000);

            //Will print "Found 2 documents"
            Console.WriteLine ("Found {0} documents", q1result.TotalHits);

            var q2 = new TermQuery (new Term ("multival", "val2"));
            var q2result = searcher.Search (q2, 1000);
            //Will print "Found 1 documents"
            Console.WriteLine ("Found {0} documents", q2result.TotalHits);
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X