2016-12-23 3 views
0

Предполагая, что у меня есть родительский класс, который я фильтрую по различным свойствам, один из которых является свойством, являющимся массивом элементов. Теперь скажите, что я хочу вернуть родительский элемент только в том случае, если мой массив элементов как указано выше значения min и ниже максимального значения ... это нормально, я могу работать, что бит; Что делать, если я тогда хочу затем сортировать по фильтрованной результирующего набора этих элементовФильтр Raven DB на подмножество элементов массива и сортировка по самым дешевым результатам результатов фильтра.

я сделал пример AC# скрипку, чтобы показать, что им пытаются достичь: https://dotnetfiddle.net/mV4d28 (обратите внимание, что foo2 возвращается первым, даже если Foo1 имеет элементы в своем массиве, которые меньше, чем в foo2)

Как мне нужно сделать это с помощью индекса, мне нужен индекс, чтобы иметь возможность вычислять заказ на основе критериев фильтра, используемых в моем запросе.

Я знаю, что у elasticsearch есть внутренняя функция хитов, которая дозирует это, и монго имеет трубопроводы, которые также дозаправляют это, поэтому я уверен, что у Ворона должен быть способ сделать это тоже?

Я надеялся, используя только индекс и преобразование с колясками я мог бы добиться этого, так что я пробовал:

мой индекс и трансформировать внешний вид, как этот

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. Есть ли другой, чтобы достичь того, что я хочу, используя прогнозы или пересечение или ранжирование или уменьшить метод try?

Я думаю, если я должен был, возможно, я мог бы использовать 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(); 
    } 
} 

затем сделать где фильтр и порядок по п с использованием индекса и преобразование переходящего в том же самом коляски, которые я использую в фильтре где. однако я не уверен, что это сработает? Что еще более важно, я не уверен, как я собираюсь получить сортировку dll в плагинах, т. Е. Какое пространство имен должно пройти под классом, какие пространства имен нужно дозировать, нужно импортировать, какое название названия сборки нужно использовать и т. Д. Согласно https://ravendb.net/docs/article-page/3.5/csharp/server/plugins/what-are-plugins i просто нужно отбросить dll, и ворон сделает это, но я не могу найти, какое пространство имен мне нужно ссылаться на IndexEntriesToComparablesGenerator?

im используя 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

как предупреждение/примечание, используя трансформации для фильтрации ворон, означает, что вы не можете использовать пейджинг. Кажется, что ворон применяет пейджинг после индекса и до преобразования. кажется, что его ограничение ворона не в состоянии делать внутренние хиты, такие как elasticsearch –