2016-12-23 28 views
0

假设我有一个父类,我过滤各种属性,其中之一是属性是一个项目的数组。 现在说,我只想返回父项目,如果我的数组的项目如上面的最小值和最大值以下...这很好,我可以工作一点; 如果我再要,然后排序经过滤的结果集Raven DB过滤器上的数组项的子集和排序上最便宜的过滤器结果项目

我做了一个C#小提琴例子来说明什么即时试图实现这些项目的: https://dotnetfiddle.net/mV4d28 (注意,foo2的第一,即使foo1返回在它的数组中的项目少于foo2中的项目)

因为我需要使用索引来执行此操作,所以我需要该索引能够根据我的查询中使用的筛选条件计算顺序。

我知道elasticsearch有一个内在的命中功能,这种情况下,mongo的管道也是这样的,所以我确信Raven也有办法做到这一点吗?

我只使用指标,希望和推着婴儿车的变换,我可以做到这一点,所以我试了一下:

我的索引和改造这个样子的

public class familyTransfrom : AbstractTransformerCreationTask<ParentItem> 
{ 
    public class Result : ParentItem{ 
     public double[] ChildItemValuesFiltered { get; set; } 
    } 
    public familyTransfrom(){ 
     TransformResults = parents => from parent in parents 
     let filterMinValue = Convert.ToDouble(ParameterOrDefault("FilterMinValue", Convert.ToDouble(0)).Value<double>()) 
     let filterMaxValue = Convert.ToDouble(ParameterOrDefault("FilterMaxValue", Convert.ToDouble(9999)).Value<double>()) 
     select new Result{ 
      ParentItemId = parent.ParentItemId, 
      ParentItemName = parent.ParentItemName, 
      ParentItemValue = parent.ParentItemValue, 
      //ChildItemValuesFiltered = parent.ChildItems.Where(p => p.ChildItemValues.Any(y => Convert.ToDouble(y) >= Convert.ToDouble(filterMinValue) && Convert.ToDouble(y) <= Convert.ToDouble(filterMaxValue))).SelectMany(t => t.ChildItemValues).ToArray<double>(), 
      ChildItemValuesFiltered = parent.ChildItems.SelectMany(p => p.ChildItemValues.Where(y => Convert.ToDouble(y) >= Convert.ToDouble(filterMinValue) && Convert.ToDouble(y) <= Convert.ToDouble(filterMaxValue))).ToArray<double>(), 
      ChildItems = Recurse(parent, x => x.ChildItems).Select(y => y).ToArray()  
     }; 
    } 
} 
public class familyIndex : AbstractIndexCreationTask<ParentItem>{ 
     public class Result : ParentItem { 
       public double[] ChildItemValues { get; set; } 
     }    
     public familyIndex(){ 
      Map = parents => from parent in parents 
       select new Result{ 
        ParentItemId = parent.ParentItemId, 
        ParentItemName = parent.ParentItemName, 
        ParentItemValue = parent.ParentItemValue, 
        ChildItemValues = parent.ChildItems.SelectMany(p => p.ChildItemValues.Select(y => y)).ToArray(), 
        ChildItems = Recurse(parent, x => x.ChildItems).Select(y => y).ToArray() 
       };                    
       Index("ParentItemId", FieldIndexing.Analyzed); 
       Index("ParentItemName", FieldIndexing.Analyzed); 
       Index("ParentItemValue", FieldIndexing.Analyzed); 
     Index("ChildItemValues", FieldIndexing.Analyzed); 
     Index("ChildItems", FieldIndexing.Analyzed); 
      } 
} 

我的查询如下,(此使用实况乌鸦操场所以这应该只是工作开箱即用它,你想使用它)

using (IDocumentStore store = new DocumentStore { Url = "http://live-test.ravendb.net/", DefaultDatabase = "altha" }) 
{ 
    store.Initialize(); 
    using (IDocumentSession session = store.OpenSession()) 
    { 
     if(1 == 2){   
      //foreach (ParentItem element in data.OfType<ParentItem>()) { 
      // session.Store((ParentItem)element); 
      // session.SaveChanges(); 
      //} 
      new familyIndex().Execute(store); 
      new familyTransfrom().Execute(store); 
     }else{ 
      double filterMinValue = 3.0; 
      double filterMaxValue = 4.0; 
      var results = session 
       .Advanced 
       .DocumentQuery<familyIndex.Result,familyIndex>() 
       .WhereBetweenOrEqual("ChildItemValues", filterMinValue, filterMaxValue) 
       .SetResultTransformer<familyTransfrom, familyTransfrom.Result>() 
       .SetTransformerParameters(new Dictionary<string, RavenJToken> { 
        { "FilterMinValue", filterMinValue }, 
        { "FilterMaxValue", filterMaxValue } }) 
       .OrderBy("ChildItemValues") 
       .OfType<ParentItem>().ToList(); 
       results.Dump();       
    }} 
} 

我发现什么是我不能使用“ChildItemValuesFiltered”从将结果转换为其非索引。所以除非我能通过变换的结果命令?我无法得到这个工作,因为它虽然它正确地过滤它dosnt命令。 是否有另一个实现我想要使用投影或交集或排名或减少尝试方法?

我在想,如果我不得不或许我可以使用https://ravendb.net/docs/article-page/3.5/csharp/indexes/querying/sorting#custom-sorting

,做这样的事情:

public class SortByNumberOfCharactersFromEnd : IndexEntriesToComparablesGenerator 
{ 
    private readonly double filterMinValue; 
    private readonly double filterMinValue; 

    public SortByNumberOfCharactersFromEnd(IndexQuery indexQuery) 
     : base(indexQuery) 
    { 
     filterMinValue = IndexQuery.TransformerParameters["FilterMinValue"].Value<double>();  // using transformer parameters to pass the length explicitly 
     filterMaxValue = IndexQuery.TransformerParameters["FilterMaxValue"].Value<double>(); 
    } 

    public override IComparable Generate(IndexReader reader, int doc) 
    { 
     var document = reader.Document(doc); 
     double[] childItemValues = (double[])document.GetValues("ChildItemValuesFiltered").Select(double.Parse).ToArray();   // this field is stored in index 
     return childItemValues.Where(x => x >= min && x <= max).Min(); 
    } 
} 

然后做一个地方滤波器和为了利用指数条款和改造通过在同一prams,我用在哪里过滤器。但我不知道这是否会工作? 更重要的是,我不知道我如何去获取排序dll到插件,即什么名称空间应该类下,什么名称空间剂量它需要导入,它需要使用什么组装名称剂量等 根据https://ravendb.net/docs/article-page/3.5/csharp/server/plugins/what-are-plugins我只需要放入DLL和乌鸦会这个了,但我似乎无法找到我需要引用IndexEntriesToComparablesGenerator什么名称空间?

即时通讯使用linqpad 5来测试我的东西...所以为了使用自定义命令我必须引用类

任何提示或建议或如何公会/例子欢迎

回答

0

所以也没发生,我认为我可以做过滤在变换

TransformResults = parents => from parent in parents 
     let filterMinValue = Convert.ToDouble(ParameterOrDefault("FilterMinValue", Convert.ToDouble(0)).Value<double>()) 
     let filterMaxValue = Convert.ToDouble(ParameterOrDefault("FilterMaxValue", Convert.ToDouble(9999)).Value<double>()) 
     select new { 
      ParentItemId = parent.ParentItemId, 
      ParentItemName = parent.ParentItemName, 
      ParentItemValue = parent.ParentItemValue, 
      //ChildItemValuesFiltered = parent.ChildItems.Where(p => p.ChildItemValues.Any(y => Convert.ToDouble(y) >= Convert.ToDouble(filterMinValue) && Convert.ToDouble(y) <= Convert.ToDouble(filterMaxValue))).SelectMany(t => t.ChildItemValues).ToArray<double>(), 
      ChildItemValuesFiltered = parent.ChildItems.SelectMany(p => p.ChildItemValues.Where(y => Convert.ToDouble(y) >= Convert.ToDouble(filterMinValue) && Convert.ToDouble(y) <= Convert.ToDouble(filterMaxValue))).ToArray<double>(), 
      ChildItems = Recurse(parent, x => x.ChildItems).Select(y => y).ToArray()  
     } into r 
     where r.ChildItemValuesFiltered.Length > 0 
     orderby r.ChildItemValuesFiltered.Min() 
     select r; 

这给了我什么,我想,这里的示例查询:

http://live-test.ravendb.net/databases/altha/indexes/familyIndex?start=0&pageSize=25&resultsTransformer=familyTransfrom&tp-FilterMinValue=3&tp-FilterMaxValue=4

我不能居功这作为乌鸦家伙帮助我,但分享知识为他人

+0

只是作为一个警告/旁注,使用变换在乌鸦过滤意味着你不能使用分页。看来,乌鸦在索引之后和变换之前应用分页。似乎它是乌鸦不能做弹性搜索等内部命中的限制 –