在ravendb中按自定义类型排序
Sorting by custom type in ravendb
我有这个class
class MyType{
public System.Version Version { get; set; }
}
我有一个 json 转换器,可以使用 Version.Parse
和 Version.ToString()
将 Version
转换为 string
。所以我的文件是这样的:
{
"version": "1.0.0"
}
现在,我想按那个字段排序,我不想使用默认的字典排序,我想使用 System.Version
的。
我试过这个:
public override IndexDefinition CreateIndexDefinition()
{
return new IndexDefinition
{
Map = "from q in docs.MyTypes select new { Version = Version.Parse(q.Version) }",
SortOptions = {
{ "Version", SortOptions.Custom }
}
};
}
但我得到一个例外:
System.NullReferenceException: Object reference not set to an instance of an object.
at Lucene.Net.Search.SortField.GetComparator(Int32 numHits, Int32 sortPos)
at Lucene.Net.Search.FieldValueHitQueue.OneComparatorFieldValueHitQueue..ctor(SortField[] fields, Int32 size)
at Lucene.Net.Search.FieldValueHitQueue.Create(SortField[] fields, Int32 size)
at Lucene.Net.Search.TopFieldCollector.Create(Sort sort, Int32 numHits, Boolean fillFields, Boolean trackDocScores, Boolean trackMaxScore, Boolean docsScoredInOrder)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Int32 nDocs, Sort sort, Boolean fillFields)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Int32 nDocs, Sort sort)
还有其他方法吗?还是可以修复此代码?
编辑(解决方案)
作为 我们最终得到了这个代码:
public class SortByVersionIndex<T> : AbstractIndexCreationTask<T>
where T : IVersionable
{
public SortByVersionIndex()
{
Map = xs => from x in xs
let v = Version.Parse(x.Version.ToString())
select new
{
Version = v.Build + v.Minor * 1000 + v.Major * 100000
};
Sort(x => x.Version, SortOptions.Long);
}
public override string IndexName => $"{typeof(T).Name}/SortByVersion";
}
我们需要像这样的索引用于多个集合,这就是为什么我们必须使其通用并覆盖 IndexName
Version.Parse(x.Version.ToString())
是一种在 c# 中静态输入代码的方法,x.Version
是服务器上的字符串。
无法在 RavenDB 中提供自定义排序器。
自定义选项在那里是因为它是我们公开的 Lucene 功能的直接副本。
您可以做的是在索引时创建版本的实例,然后转换为长整数,然后进行比较。
我有这个class
class MyType{
public System.Version Version { get; set; }
}
我有一个 json 转换器,可以使用 Version.Parse
和 Version.ToString()
将 Version
转换为 string
。所以我的文件是这样的:
{
"version": "1.0.0"
}
现在,我想按那个字段排序,我不想使用默认的字典排序,我想使用 System.Version
的。
我试过这个:
public override IndexDefinition CreateIndexDefinition()
{
return new IndexDefinition
{
Map = "from q in docs.MyTypes select new { Version = Version.Parse(q.Version) }",
SortOptions = {
{ "Version", SortOptions.Custom }
}
};
}
但我得到一个例外:
System.NullReferenceException: Object reference not set to an instance of an object.
at Lucene.Net.Search.SortField.GetComparator(Int32 numHits, Int32 sortPos)
at Lucene.Net.Search.FieldValueHitQueue.OneComparatorFieldValueHitQueue..ctor(SortField[] fields, Int32 size)
at Lucene.Net.Search.FieldValueHitQueue.Create(SortField[] fields, Int32 size)
at Lucene.Net.Search.TopFieldCollector.Create(Sort sort, Int32 numHits, Boolean fillFields, Boolean trackDocScores, Boolean trackMaxScore, Boolean docsScoredInOrder)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Int32 nDocs, Sort sort, Boolean fillFields)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Int32 nDocs, Sort sort)
还有其他方法吗?还是可以修复此代码?
编辑(解决方案)
作为
public class SortByVersionIndex<T> : AbstractIndexCreationTask<T>
where T : IVersionable
{
public SortByVersionIndex()
{
Map = xs => from x in xs
let v = Version.Parse(x.Version.ToString())
select new
{
Version = v.Build + v.Minor * 1000 + v.Major * 100000
};
Sort(x => x.Version, SortOptions.Long);
}
public override string IndexName => $"{typeof(T).Name}/SortByVersion";
}
我们需要像这样的索引用于多个集合,这就是为什么我们必须使其通用并覆盖 IndexName
Version.Parse(x.Version.ToString())
是一种在 c# 中静态输入代码的方法,x.Version
是服务器上的字符串。
无法在 RavenDB 中提供自定义排序器。 自定义选项在那里是因为它是我们公开的 Lucene 功能的直接副本。 您可以做的是在索引时创建版本的实例,然后转换为长整数,然后进行比较。