开发者

Lucene.NET "OR"

How do I do an "OR" in Lucene.NET. Basically what I have is an array of IDs and I want to return any records where a particular field contains any of the values. I previously was doing this with just one value, but now I want to convert the following code so that MetaDataID is an array of possible values instead of one single value.

if (MetaDataID.Length > 0)
    completeQuery.Add(new Q开发者_开发百科ueryParser("MetaData", new StandardAnalyzer()).Parse(MetaDataID), BooleanClause.Occur.MUST);


When combining Lucene queries where you want any index record that contains any one of multiple possible values with additional criteria that must also be met, create multiple boolean query objects.

For the first group of "OR" conditions:

BooleanQuery booleanQueryInner = new BooleanQuery();
Query query1 = new TermQuery(new Term("id", "<id 1>"));
Query query2 = new TermQuery(new Term("id", "<id 2>"));
Query query3 = new TermQuery(new Term("id", "<id 3>"));
Query query4 = new TermQuery(new Term("id", "<id 4>"));
booleanQueryInner.add(query1, BooleanClause.Occur.SHOULD);
booleanQueryInner.add(query2, BooleanClause.Occur.SHOULD);
booleanQueryInner.add(query3, BooleanClause.Occur.SHOULD);
booleanQueryInner.add(query4, BooleanClause.Occur.SHOULD);

Now combine with other conditions in query

BooleanQuery booleanQueryOuter = new BooleanQuery();
booleanQueryOuter.add(booleanQueryInner, BooleanClause.Occur.MUST);
booleanQueryOuter.add(boolenaQueryOtherConditions, BooleanClause.Occur.MUST);

Now index records will only be returned if they meet one of the conditions in the inner "OR" group and also meet the conditions in the "other conditions" query.


You need to use BooleanClause.Occur.SHOULD instead of BooleanClause.Occur.MUST

e.g.:

BooleanQuery booleanQuery = new BooleanQuery();
Query query1 = new TermQuery(new Term("id", "<id 1>"));
Query query2 = new TermQuery(new Term("id", "<id 2>"));
booleanQuery.add(query1, BooleanClause.Occur.SHOULD);
booleanQuery.add(query2, BooleanClause.Occur.SHOULD);


When you really want to parse your query, you just need to choose the correct Analyzer and format for your query.

The StandardAnalyzer is not a good choice when you are indexing anything but english full text, especially not in your case! It filters out numbers!

The shortest solution in you case is to create an analyzer that tokenizes at a separator and combine your object into a string.

Example:

Create a Tokenizer that splits at typical seperators and an Analyzer that uses it

using System.IO;
using System.Linq;
using Lucene.Net.Analysis;

namespace Project.Analysis
{
    public class TermTokenizer : LetterTokenizer
    {
        // some static separators
        private static readonly char[] NONTOKEN_CHARS = new char[] { ',', ';', ' ', '\n', '\t' };

        protected override bool IsTokenChar(char c)
        {
            return !NONTOKEN_CHARS .Contains(c);
        }
    }

    public class LowerCaseTermAnalyzer : Analyzer
    {
        public override TokenStream TokenStream(string fieldName, TextReader reader)
        {
            return new LowerCaseFilter(new TermTokenizer(reader));
        }
    }
}

Use the new analyzer in your parser

(You need to include System.Linq)

if (MetaDataID.Length > 0)
{
    // the search term will look like this: "1;5;7"
    string searchTerm = string.Join(";", MetaDataID);

    // the query parser uses the new Analyzer
    QueryParser parser = new QueryParser("MetaData",new LowerCaseTermAnalyzer());

    // the parsed search term (only used internally) will look like this:
    // "MetaData:1 MetaData:5 MetaData:7", which is essentially what you want to achieve
    completeQuery.Add(new parser.Parse(MetaDataID), BooleanClause.Occur.MUST);
}


Be careful when using BooleanQuery for retrieving documents by id, because it has a limit of maximum boolean clauses.

The basic "OR" clause in Lucene is performed like this, assuming that your searchable field is named "id":

"id:1 id:2 id:3 id:4"

Instead of an "AND" query:

"+id:1 +id:2 +id:3 + id:4"

Using the standard QueryParser and a StringBuilder should do the magic for you.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜