Michael Hornfeck
Michael Hornfeck

Reputation: 1252

Wildcard search on specific terms using MultiFieldQueryParser

I am utilizing the Lucene.net version 3.0 API to create and search an index for my project. Each Document in my index has three Fields:

My requirements are this:

  1. I want a hit if a search term matches the first part of a Document's value for TransactionId. For example, if I search for "ab" then Documents with TransactionId equal to "ab-1" or "ab-2" would be hits.

  2. I only want hits when the full search term matches Agent and Lender. The search for "ab" would not return Documents where the value of Lender is "ab-1" or "ab-2".

So far, I have the following block of code:

var searcher = new IndexSearcher(FSDirectory.Open(path));
var parser = new MultiFieldQueryParser(Version.LUCENE_30, 
 new[] {"TransactionId", "Agent", "Lender"},
 new StandardAnalyzer(Version.LUCENE_30));

var query = parser.Parse(queryText);
var hits = searcher.Search(query, 200);

If queryText is "ab" then the value of query is {TransactionId:ab Agent:ab Lender:ab}

I know I am looking for it to be something like {TransactionId:ab* Agent:ab Lender:ab}

Is there any way to do this with the MultiFieldQueryParser?

Upvotes: 0

Views: 834

Answers (1)

Jf Beaulac
Jf Beaulac

Reputation: 5246

You could probably achieve that by subclassing the MultiFieldQueryParser.

The following seems to works, maybe something you can build on. Note that parsing the BooleanQuery should be recursive as you could end up with nested queries eventually.

Disclaimer: this code isnt elegant and probably breaks very easily as is, its intended as a quick example

    public class WildCardForFieldQueryParser : MultiFieldQueryParser
    {
        public WildCardForFieldQueryParser(Lucene.Net.Util.Version version, 
                                           string [] fields, 
                                           Analyzer analyzer, 
                                           HashSet<string> wildcardFields)
            :base(version, fields, analyzer)
        {
            this._wildcardFields = wildcardFields;
        }

        public override Query Parse(string query)
        {
            // clause replacement should be recursive
            Query q = base.Parse(query);
            if (q is BooleanQuery)
            {
                foreach (var clause in q as BooleanQuery)
                {
                    if (clause.Query is TermQuery && this._wildcardFields.Contains(((TermQuery)clause.Query).Term.Field))
                    {
                        clause.Query = new PrefixQuery(new Term(((TermQuery)clause.Query).Term.Field, ((TermQuery)clause.Query).Term.Text));
                    }
                }
            }
            return q;
        }
        private HashSet<string> _wildcardFields;
    }

Upvotes: 1

Related Questions