34
Dim qp1 As New QueryParser("filename", New StandardAnalyzer())
Dim qp2 As New QueryParser("filetext", New StandardAnalyzer())
.
.

I am using the 'Lucene.Net' library and have the following question.

Instead of creating two separate QueryParser objects and using them to obtain two Hits objects, is it possible perform a search on both fields using a single QueryParser object, so that I have only one Hits object which gives me the overall score of each Document?

peak
  • 105,803
  • 17
  • 152
  • 177
user57175
  • 3,284
  • 9
  • 32
  • 26

4 Answers4

77

There are 3 ways to do this.

The first way is to construct a query manually, this is what QueryParser is doing internally. This is the most powerful way to do it, and means that you don't have to parse the user input if you want to prevent access to some of the more exotic features of QueryParser:

IndexReader reader = IndexReader.Open("<lucene dir>");
Searcher searcher = new IndexSearcher(reader);

BooleanQuery booleanQuery = new BooleanQuery();
Query query1 = new TermQuery(new Term("filename", "<text>"));
Query query2 = new TermQuery(new Term("filetext", "<text>"));
booleanQuery.add(query1, BooleanClause.Occur.SHOULD);
booleanQuery.add(query2, BooleanClause.Occur.SHOULD);
// Use BooleanClause.Occur.MUST instead of BooleanClause.Occur.SHOULD
// for AND queries
Hits hits = searcher.Search(booleanQuery);

The second way is to use MultiFieldQueryParser, this behaves like QueryParser, allowing access to all the power that it has, except that it will search over multiple fields.

IndexReader reader = IndexReader.Open("<lucene dir>");
Searcher searcher = new IndexSearcher(reader);

Analyzer analyzer = new StandardAnalyzer();
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(
                                        new string[] {"filename", "filetext"},
                                        analyzer);

Hits hits = searcher.Search(queryParser.parse("<text>"));

The final way is to use the special syntax of QueryParser see here.

IndexReader reader = IndexReader.Open("<lucene dir>");
Searcher searcher = new IndexSearcher(reader);    

Analyzer analyzer = new StandardAnalyzer();
QueryParser queryParser = new QueryParser("<default field>", analyzer);
// <default field> is the field that QueryParser will search if you don't 
// prefix it with a field.
string special = "filename:" + text + " OR filetext:" + text;

Hits hits = searcher.Search(queryParser.parse(special));

Your other option is to create new field when you index your content called filenameandtext, into which you can place the contents of both filename and filetext, then you only have to search one field.

Sam Doshi
  • 4,376
  • 1
  • 21
  • 20
  • 1
    with the MultiFieldQueryParser, how should the query look like? Could you give an example for "" in the line `queryParser.parse("")`? – alvas Jan 13 '12 at 00:35
  • 1
    how to i allow query for different fields using the MultiFieldQueryParser? let's say i want to query for `filename:testfile.txt AND filetext:"Singapore food"`. – alvas Jan 13 '12 at 00:37
4

Just build a query string with each term:

"filename:searchText OR filetext:searchText"

It doesn't matter what you pass as the initial field in QueryParser's constructor. Just make sure you call .Parse() on your query string to get a Query object back to execute.

If you want to use an "and" search:

"+filename:searchText +filetext:searchText"
Bob King
  • 25,372
  • 6
  • 54
  • 66
2

** you can also use MultiFieldQueryParser to search in all available fields.**

E.g

Dim queryParser = New MultiFieldQueryParser(Version.LUCENE_29, 
indexReader__1.GetFieldNames(IndexReader.FieldOption.ALL).ToArray(), analyzer)

here is complete an example.

//get index directory
Dim directory As Directory = FSDirectory.Open(New DirectoryInfo(HostingEnvironment.MapPath(VirtualIndexPath)))

//get analyzer
Dim analyzer As Analyzer = New StandardAnalyzer(Version.LUCENE_29)

//get index reader and searcher
Dim indexReader__1 As IndexReader = IndexReader.Open(directory, True)
Dim indexSearch As Searcher = New IndexSearcher(indexReader__1)

//add all possible fileds in multifieldqueryparser using indexreader getFieldNames method
Dim queryParser = New MultiFieldQueryParser(Version.LUCENE_29, indexReader__1.GetFieldNames(IndexReader.FieldOption.ALL).ToArray(), analyzer)
Dim query = queryParser.Parse(Criteria)
Dim resultDocs As TopDocs = Nothing

//perform search
resultDocs = indexSearch.Search(query, indexReader__1.MaxDoc())
Dim hits = resultDocs.scoreDocs

hope that help

Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
vijay shiyani
  • 766
  • 7
  • 19
1

for each field create a query from the above queryparsers, then add the query to a booleanquery stating that it "must" occur.

Alternatively, check out the MultiFieldQueryParser, which is a simplified way of doing it.

Doug
  • 494
  • 8
  • 14