2012-04-10 19 views
4

我正在使用Advanced.LuceneQuery例如如何搜索数字落在2个值之间的文档?

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); 

} 

谢谢 斯蒂芬

回答

6
的方法

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

Price_Range:[FromNumber TO ToNumber] 

见Lucene的query syntax文档的完整信息。您还需要以正确的十六进制格式输入数字。确保你使用Raven.Abstractions命名空间中的NumberUtils class的内置函数来为你做这件事,而不是自己做。

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

+0

马特,谢谢。我使用字符串生成器版本的原因是因为我没有发现能够将查询连接到开发周期的后期。请参阅https://groups.google.com/forum/?fromgroups#!topic/ravendb/CKXphUYmGL4 – 2012-04-10 22:32:55

5

重申马特的评论。你真的想避免手工构建查询。 Lucene查询API有一个方法,WhereBetween可以完成这一切。 请注意,这里有很多魔法,用于处理参数格式等,这些都是你真正想要考虑的。

+0

谢谢Oren。但是那里没有伤害吗?数据库返回数据的速度如此之快,以至于它的数据传输速度非常快,而且从可读性和维护角度看,代码看起来并不那么糟糕,所以除非你告诉我我必须改变它,否则......目前 :) – 2012-04-11 17:33:34

相关问题