假设我有一个父类,我过滤各种属性,其中一个属性是一个 items 数组。现在说,如果我的项目数组高于最小值且低于最大值,我只想返回父项目......这很好,我可以解决这个问题;如果我想然后对这些项目的过滤结果集进行排序怎么办
我制作了 ac# fiddle 示例来展示我试图实现的目标: https ://dotnetfiddle.net/mV4d28 (请注意,首先返回 foo2,即使 foo1 的数组中的项目少于 foo2 中的项目)
由于我需要使用索引来执行此操作,因此我需要索引能够根据我的查询中使用的过滤条件来计算顺序。
我知道 elasticsearch 有一个内部 hits 函数可以给这个剂量,而 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”作为它的非索引。所以除非我可以通过转换的结果来订购?我无法让它工作,尽管它正确过滤了它的顺序。是否有另一种方法可以使用投影或交集或排名或减少尝试方法来实现我想要的?
我在想,如果我必须这样做,也许我可以使用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();
}
}
然后使用 index 和 transform 执行 where 过滤器和 order by 子句,传入我在 where 过滤器中使用的相同婴儿车。但是我不确定这是否可行?更重要的是,我不确定如何将排序 dll 放入插件中,即类应该在什么命名空间下,它需要导入什么命名空间,它需要使用什么程序集名称等根据https:// ravendb.net/docs/article-page/3.5/csharp/server/plugins/what-are-plugins我只需要将 dll 放入其中,raven 会这样做,但是我似乎找不到我需要的名称空间IndexEntriesToComparablesGenerator 的参考?
我正在使用 linqpad 5 来测试我的东西……所以为了使用自定义顺序,我必须引用该类
欢迎任何提示或建议或如何行会/示例