4

我正在使用 Advanced.LuceneQuery 例如

RavenQueryStatistics stats = null;
vm.Products = DocumentSession.Advanced.LuceneQuery<Product>("Products/Index")
            .Statistics(out stats)
            .Where(searchExpression)
            .OrderBy(columnToSortBy)
            .Skip((vm.PageIndex - 1) * vm.PageSize)
            .Take(vm.PageSize)
            .ToArray()
            ;

有了这个索引

public Products_Index()
{
    Map = products => from p in products
                      select new
                      {
                          p.ItemNum,
                          p.BrandName,
                          p.ProductName,
                          p.Catalog,
                          p.UOM,
                          p.CasePack,
                          p.AveWeight,
                          p.CatalogId,
                          p.HasPicture,
                          p.INFO2,
                          p.IsOfflineSupplierItem,
                          p.IsRebateItem,
                          p.IsSpecialOrderItem,
                          p.IsSpecialPriceItem,
                          p.Price
                      };

    Indexes.Add(x => x.INFO2, FieldIndexing.Analyzed);
    Indexes.Add(x => x.CatalogId, FieldIndexing.Analyzed);
    Indexes.Add(x => x.HasPicture, FieldIndexing.Analyzed);
    Indexes.Add(x => x.IsOfflineSupplierItem, FieldIndexing.Analyzed);
    Indexes.Add(x => x.IsRebateItem, FieldIndexing.Analyzed);
    Indexes.Add(x => x.IsSpecialOrderItem, FieldIndexing.Analyzed);
    Indexes.Add(x => x.IsSpecialPriceItem, FieldIndexing.Analyzed);
    Indexes.Add(x => x.Price, FieldIndexing.Analyzed);
}

并且要执行的典型表达式如下所示

"INFO2:(blue*) AND INFO2:(pen*) AND HasPicture:(True) AND IsSpecialOrderItem:(True) AND IsRebateItem:(True) AND IsOfflineSupplierItem:(True) AND CatalogId:(736275001)" 

现在我需要合并基于价格列/索引的范围搜索。构造我的 where 子句的那部分的语法是什么?

要求是

价格 >= FromNumber 价格 <= ToNumber

编辑:构造 where 子句的方法

private void ProductSearch(ProductSearchViewModel vm)
{

    var terms = vm.SearchTerm
        .ToLower()
        .Split(new char[] { ' ' });

    // Start buildeing up the query
    var sb = new StringBuilder();

    // terms
    foreach (string term in terms)
    {
        sb.AppendFormat("INFO2:({0}*) AND ", term);
    }

    if (vm.Filters != null)
    {

        // picture 
        if (vm.Filters.IsAtrFilterPictureSelected)
        {
            sb.AppendFormat("HasPicture:({0}) AND ", vm.Filters.IsAtrFilterPictureSelected);
        }
        // special order
        if (vm.Filters.IsAtrFilterSpecialOrderSelected)
        {
            sb.AppendFormat("IsSpecialOrderItem:({0}) AND ", vm.Filters.IsAtrFilterSpecialOrderSelected);
        }
        // special price
        if (vm.Filters.IsAtrFilterSpecialPriceSelected)
        {
            sb.AppendFormat("IsSpecialPriceItem:({0}) AND ", vm.Filters.IsAtrFilterSpecialPriceSelected);
        }
        // rebate
        if (vm.Filters.IsAtrFilterRebateSelected)
        {
            sb.AppendFormat("IsRebateItem:({0}) AND ", vm.Filters.IsAtrFilterRebateSelected);
        }
        // offline supplier
        if (vm.Filters.IsAtrFilterOfflineItemSelected)
        {
            sb.AppendFormat("IsOfflineSupplierItem:({0}) AND ", vm.Filters.IsAtrFilterOfflineItemSelected);
        }
        // catalog
        if (vm.Filters.CatalogSelected > 0)
        {
            sb.AppendFormat("CatalogId:({0}) AND ", vm.Filters.CatalogSelected);
        }
        // price range
        if (vm.Filters.PriceFrom > 0 && vm.Filters.PriceTo > 0)
        {
            sb.AppendFormat("Price_Range:[{0} TO {1}]", NumberUtil.NumberToString((double)vm.Filters.PriceFrom), NumberUtil.NumberToString((double)vm.Filters.PriceTo));
        }

    }

    // remove the last 'AND' from the string 
    var searchExpression = sb.ToString();
    if (searchExpression.EndsWith("AND "))
    {
        searchExpression = searchExpression.Substring(0, searchExpression.LastIndexOf("AND "));
    }

    // trace it out
    Logger.WriteMessage(Infrastructure.Logging.LogLevel.Info, "Search Term: " + searchExpression);

    Stopwatch watch = Stopwatch.StartNew();

    string columnToSortBy = string.Empty;
    if (vm.GridParams != null)
    {
        // Luncene specific way of ordering
        columnToSortBy = vm.GridParams.sidx ?? "Price";
        columnToSortBy = vm.GridParams.sord == "asc" ? "+" + columnToSortBy : "-" + columnToSortBy;
    }

    // execution of query
    RavenQueryStatistics stats = null;
    vm.Products = DocumentSession.Advanced.LuceneQuery<Product>("Products/Index")
                .Statistics(out stats)
                .Where(searchExpression)
                .OrderBy(columnToSortBy)
                .Skip((vm.PageIndex - 1) * vm.PageSize)
                .Take(vm.PageSize)
                .ToArray()
                ;

    watch.Stop();
    vm.TotalResults = stats.TotalResults;
    Logger.WriteMessage(Infrastructure.Logging.LogLevel.Info, "Search Time: " + watch.ElapsedMilliseconds);

}

谢谢你,斯蒂芬

4

2 回答 2

6

你需要这样的东西(注意“_Range”):

Price_Range:[FromNumber TO ToNumber]

有关完整信息,请参阅 Lucene查询语法文档。您还需要以正确的十六进制格式输入数字。确保您使用 Raven.Abstractions 命名空间中NumberUtils 类中的内置函数为您执行此操作,而不是您自己执行此操作。

但是,您是否有理由使用低级 Lucene API 并手动构建查询?有一个支持 LINQ 的强类型 API 可以为您完成很多工作(session.Query<T>())。

于 2012-04-10T22:09:54.207 回答
5

重申马特的评论。您真的希望避免手动构建查询。Lucene Query API 有一个方法 WhereBetween 可以为您完成所有工作。请注意,那里有很多魔法,比如参数格式化等,你真的想考虑。

于 2012-04-11T05:43:26.627 回答