0

I'm trying to implement my own custom SearchService. As I understand it

// If I wanted to query "+name:camera +price:[100 TO 150] +location:thailand"
searchBuilder.WithField("name", "camera").ExactMatch().Mandatory();
searchBuilder.WithinRange("price", 100, 150, true, true).Mandatory();
searchBuilder.WithField("location", "thailand").ExactMatch().Mandatory();

No problem here. But how do I approach a query with grouping (clauses with parentheses)?

// How do I query "+name:camera +(price:[100 TO 150] cost:[100 TO 150]) +(bundle-price:[100 TO 150] total-price:[100 TO 150])"?
// Since the ISearchBuilder interface doesn't support grouping, the only other way
// I could think of is to use the freestyle ISearchBuilder.Parse() to construct the query.
// However this doesn't return any hits:
searchBuilder.WithField("name", "camera").ExactMatch().Mandatory();
searchBuilder.Parse("price", "[100 TO 150] cost:[100 TO 150]", false).Mandatory();
searchBuilder.Parse("bundle-price", "[100 TO 150] total-price:[100 TO 150]", false).Mandatory();

There's just isn't enough information for ISearchBuilder.Parse() to determine the datatype of the range (whether it's int, float or double). Looks like Luke is having this problem too which can be circumvented using XML Query Parser that I don't think Lucene.Net has:

Lucene numeric range search with LUKE


I was thinking that if the ISearchBuilder has a method to allow us to insert our own Query

// /src/Orchard/Indexing/ISearchBuider.cs
public interface ISearchBuilder {
    ISearchBuilder WithQuery(Query query);
}

// /src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs
public class LuceneSearchBuilder : ISearchBuilder {
    public ISearchBuilder WithQuery(Query query) {
        CreatePendingClause();
        _query = query;
        return this;
    }
}

public class CustomSearchService {
    public void Search() {
        // construct our own custom queries
        var booleanQuery1 = new BooleanQuery();
        booleanQuery1.Add(NumericRangeQuery.NewDoubleRange("price", 100, 150, true, true), Occur.SHOULD);
        booleanQuery1.Add(NumericRangeQuery.NewDoubleRange("cost", 100, 150, true, true), Occur.SHOULD);

        var booleanQuery2 = new BooleanQuery();
        booleanQuery2.Add(NumericRangeQuery.NewDoubleRange("bundle-price", 100, 150, true, true), Occur.SHOULD);
        booleanQuery2.Add(NumericRangeQuery.NewDoubleRange("total-price", 100, 150, true, true), Occur.SHOULD);

        searchBuilder.WithField("name", "camera").ExactMatch().Mandatory();
        // insert our custom queries into the SearchBuilder using the newly added interface method (ISearchBuilder.WithQuery()) above
        searchBuilder.WithQuery(booleanQuery1).Mandatory();
        searchBuilder.WithQuery(booleanQuery2).Mandatory();
    }
}

then we can construct more complex and flexible queries.

Update

Someone has raised this issue before at https://github.com/OrchardCMS/Orchard/issues/5764

Community
  • 1
  • 1
Twisted Whisper
  • 1,166
  • 2
  • 15
  • 27

1 Answers1

-1

You probably should use Search API with facets. Here is an exact presentation: https://www.youtube.com/watch?v=7v5qSR4g7E0 and some notes here: http://weblogs.asp.net/bleroy/orchard-harvest-2015-search-api

urbanit
  • 473
  • 3
  • 9
  • I've already seen this earlier, but I can't see how this relates to my problem. Would you please elaborate further? From the looks of it, facet is like applying a simple clause as a filter to the existing query, not a complex group of clauses. Moreover, faceted search emphasize on the summary of the number of hits. I'm more interested in the actual hits (documents returned from the hits) rather than just hit count. – Twisted Whisper Feb 25 '16 at 11:24