2013-07-17 125 views
2

我在C#Asp.Net中使用RavenDB,并且在应用OrderBy时通过子集合内的值进行排序时遇到问题。我的模型的一个基本的例子是:使用RavenDB在子集合上的OrderBy

public class Record 
{ 
    public string Id { get; set; } 

    public string Name {get; set; } 

    public Field[] Fields { get; set; } 
} 

public class Field 
{ 
    public string Name { get; set; } 

    public string Value { get; set; } 
} 

这节省下来到RavenDB像这样

{ 
    "Name": "A Name Of Somesort" 
    "Fields": [ 
     { 
      "Name": "Colour", 
      "Value": "Red" 
     }, 
     { 
      "Name": "Size", 
      "Value": "Large" 
     } 
    ] 
} 

想象大量的这些记录保存到数据库中,我能得到这个数据等的页面所以

using (var session = documentStore.OpenSession("TestDB")) 
{ 
    var result = session.Query<Record>().Skip(0).Take(10).ToList(); 
} 

我想什么做的是能够根据字段值对记录进行排序(例如:在一个字段的名称的值排序的记录是“颜色”)

编辑:

为了帮助解释进一步,什么林想实现的是类似下面,但是这不是在RavenDB允许的,所以我需要找到这样做的另一种方式(如果它甚至有可能)

using (var session = documentStore.OpenSession("TestDB")) 
{ 
    var result = session.Query<Record>() 
       .OrderBy(v => v.Fields.First(f => f.Name == "Colour").Value) 
       .Skip(0) 
       .Take(10) 
       .ToList(); 
} 

这将引发具有以下消息的新的ArgumentException

Invalid computation: v.Fields.First(f => (f.Name == "Colour")).Value. You cannot use computation (only simple member expression are allowed) in RavenDB queries. 

回答

3

所以,我已经成功地得到这个工作,所以只是分享我是如何做的。

我不得不创建像下面

public class Record_ByField : AbstractIndexCreationTask<Record> 
{ 
    public Record_ByField() 
    { 
     Map = records=> from r in records 
          select new 
          { 
           _ = r.Fields 
           .Select(field => 
            CreateField(field.Name, field.Value, false, true)) 
          }; 
    } 
} 

这就意味着我可以(在色域中在这个例子中,在值)使用LuceneQuery做一个排序依据的字段值的新指数

var result = session.Advanced.LuceneQuery<Record>("Record/ByField") 
      .OrderBy("+Colour") 
      .Skip(0) 
      .Take(10) 
      .ToList(); 

要按降序排列,我可以将+前缀替换为 - 前缀(-Colour),并且我可以将任何字段名称传入此Order By。

有关在特定数据库progmmatically安装索引的信息 - 见Programmatically create index

的信息动态指标 - 见http://ravendb.net/docs/2.0/client-api/advanced/dynamic-fields

1

result.OrderBy(x => x.Field.Name)将返回作为LINQ的集合不会改变它被调用的集合,而是会返回一个具有所需结果的新集合。

所以做

result = result.OrderBy(x => x.Field.Name); 
+0

不知道这就是我要找的。我添加了一个编辑,希望进一步解释。我想要在Skip和Take之前根据其中一个字段的值对记录列表进行排序 - 在上面的示例中,它将以名称颜色显示字段的值(因此记录的字段名称为蓝色的颜色和值将高于具有被称为颜色的字段和值为红色的字段的记录) – Rob