2016-12-23 45 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

只是作爲一個警告/旁註,使用變換在烏鴉過濾意味着你不能使用分頁。看來,烏鴉在索引之後和變換之前應用分頁。似乎它是烏鴉不能做彈性搜索等內部命中的限制 –