Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lucene.NET and searching on multiple fields with specific values

Tags:

c#

lucene.net

I've created an index with various bits of data for each document I've added, each document can differ in it field name.

Later on, when I come to search the index I need to query it with exact field/ values - for example:

FieldName1 = X AND FieldName2 = Y AND FieldName3 = Z

What's the best way of constructing the following using Lucene .NET:

  • What analyser is best to use for this exact match type?
  • Upon retrieving a match, I only need one specific field to be returned (which I add to each document) - should this be the only one stored?
  • Later on I'll need to support keyword searching (so a field can have a list of values and I'll need to do a partial match).

The fields and values come from a Dictionary<string, string>. It's not user input, it's constructed from code.

Thanks,
Kieron

like image 997
Kieron Avatar asked Mar 29 '10 16:03

Kieron


1 Answers

Well, I figured it out eventually - here's my take on it (this could be completely wrong, but it works for):

public Guid? Find (Dictionary<string, string> searchTerms)
{
    if (searchTerms == null)
        throw new ArgumentNullException ("searchTerms");

    try
    {
            var directory = FSDirectory.Open (new DirectoryInfo (IndexRoot));
            if (!IndexReader.IndexExists (directory))
                return null;

            var mainQuery = new BooleanQuery ();
            foreach (var pair in searchTerms)
            {
                var parser = new QueryParser (
                    Lucene.Net.Util.Version.LUCENE_CURRENT, pair.Key, GetAnalyzer ());
                var query = parser.Parse (pair.Value);

                mainQuery.Add (query, BooleanClause.Occur.MUST);
            }

            var searcher = new IndexSearcher (directory, true);

            try
            {
                var results = searcher.Search (mainQuery, (Filter)null, 10);
                if (results.totalHits != 1)
                    return null;

                return Guid.Parse (searcher.Doc (results.scoreDocs[0].doc).Get (ContentIdKey));
            }
            catch
            {
                throw;
            }
            finally
            {
                if (searcher != null)
                    searcher.Close ();
            }
    }
    catch
    {
            throw;
    }
}
like image 168
Kieron Avatar answered Nov 15 '22 21:11

Kieron