6

書籍の Lucene.net インデックスを作成しました。すべてがうまく機能していますが、インデックスをクエリする別の方法を追加する必要があり、その方法がわかりません。

基本的に、各本には適した年齢層があります。これは、minAge と maxAge の 2 つの列で表されます。両方の列は整数です。

次のループでこれらのフィールドにインデックスを付けて保存しています

foreach (var catalogueBook in books)
{
    var book = new Book(catalogueBook.CatalogueBookNo,catalogueBook.IssueId);

    var strTitle = book.FullTitle ?? "";
    var strAuthor = book.Author ?? "";
    // create a Lucene document for this book
    var doc = new Document();

    // add the ID as stored but not indexed field, not used to query on
    doc.Add(
        new Field(
            "BookId",
            book.CatalogueBookNo.ToString(System.Globalization.CultureInfo.InvariantCulture),
            Field.Store.YES,
            Field.Index.NOT_ANALYZED_NO_NORMS,
            Field.TermVector.NO));

    // add the title and author as stored and tokenized fields, the analyzer processes the content
    doc.Add(
        new Field("FullTitle",
            strTitle.Trim().ToLower(), 
            Field.Store.YES, 
            Field.Index.ANALYZED, 
            Field.TermVector.NO));

    doc.Add(
        new Field("Author",
            strAuthor.Trim().ToLower(),
            Field.Store.YES,
            Field.Index.ANALYZED,
            Field.TermVector.NO));

    doc.Add(
        new Field("IssueId", 
            book.IssueId, 
            Field.Store.YES, 
            Field.Index.NOT_ANALYZED_NO_NORMS, 
            Field.TermVector.NO));

    doc.Add(
        new Field(
            "PublicationId",
            book.PublicationId.Trim().ToLower(),
            Field.Store.YES,
            Field.Index.NOT_ANALYZED_NO_NORMS,
            Field.TermVector.NO));

    doc.Add(
        new Field(
            "MinAge",
            book.MinAge.ToString("0000"),
            Field.Store.YES,
            Field.Index.NOT_ANALYZED_NO_NORMS,
            Field.TermVector.NO));

    doc.Add(
        new Field(
            "MaxAge",
            book.MaxAge.ToString("0000"),
            Field.Store.YES,
            Field.Index.NOT_ANALYZED_NO_NORMS,
            Field.TermVector.NO));

    doc.Add(new NumericField("Price",Field.Store.YES,true).SetDoubleValue(Convert.ToDouble(book.Price)));

    //Now we can loop through categories
    foreach(var bc in book.GetBookCategories())
    {
        doc.Add(
            new Field("CategoryId",
                bc.CategoryId.Trim().ToLower(),
                Field.Store.YES,
                Field.Index.NOT_ANALYZED_NO_NORMS,
                Field.TermVector.NO));
    }

    // add the document to the index
    indexWriter.AddDocument(doc);
}

// make lucene fast
indexWriter.Optimize();
}

ご覧のとおり、minAge フィールドと maxAge フィールドをパディングしています。これに対して TermRangeQuery を実行するのが最も簡単だと考えたからです。

ただし、Age を使用して minAge 列と maxAge 列の両方にクエリを実行し、その Age が minAge と maxAge で定義された Age 範囲内にあるかどうかを確認する必要があります。

Sqlは

Select * 
From books 
where @age >= minAge and @age <= maxAge

残念ながら、これを行う方法がわかりません。これはLucene.Netでも可能ですか?

4

2 に答える 2

10

メモリが機能する場合は、範囲クエリを利用してこれを実行できるはずです。これは事実上、標準範囲クエリの逆ですが、次のようにできるはずです。

+minAge:[* TO @age] +maxAge:[@age TO *]

または、クエリオブジェクトを作成する場合、上限または下限のnullを使用するRangeQuery(またはより適切にはNumericRangeQuery)は、制限のない範囲として機能します。

私は以前に上記の構文を使用しましたが、サポートは少し...不安定なようです。それでも問題が解決しない場合は、次のように、いつでも適切な下限(0)と上限(たとえば1000)を設定できます。

+minAge:[0000 TO @age] +maxAge:[@age TO 1000]

メトセラを除けば、これは十分に安全なはずです。

于 2012-09-28T23:05:19.160 に答える
4

上記のfemtoRgonの回答の助けを借りてこれを行うことになりました。

var q = new TermRangeQuery("MinAge", "0000",searchTerms.Age.ToString("0000"), true, true);
mainQuery.Add(q, BooleanClause.Occur.MUST);
q = new TermRangeQuery("MaxAge", searchTerms.Age.ToString("0000"),"9999", true, true);
mainQuery.Add(q, BooleanClause.Occur.MUST);

于 2012-09-29T09:44:27.033 に答える