2016-09-19 47 views
0

我有这个类,我们称之为“设备”。这个类有几个属性,其中一个是属性(字符串值)的集合属性。查询RavenDB中包含特定值的子资产集合

在RavenDB中可能有5000个“设备”实例,其中每个实例都可以在集合属性中具有字符串值列表。我们称这个属性为“MyStringValues”。 我的问题围绕着搜索ravendb的设备实例的最佳方式,该设备实例在其collection属性中包含一个字符串值。

一个非常简单的例子:

void Main() 
{ 
    var d1 = new Device(); 
    d1.Id = "device-1"; 
    d1.MyStringValues.Add("123"); 
    d2.MyStringValues.Add("456"); 

    var d2 = new Device(); 
    d2.Id = "device-2"; 
    d2.MyStringValues.Add("789"); 
    d2.MyStringValues.Add("abc"); 
} 

public class Device{ 
    public Device(){ 
     MyStringValues = new List<string>(); 
    } 
    public string Id {get;set;} 
    public IList<string> MyStringValues {get;set;} 
} 

在我寻求构建我传递一个字符串值的方法。基于该字符串我想收到一个设备。 什么是检索此“设备”的最佳方法?由于设备的数量可以达到5000我不能全部获取并开始循环。必须有更好(更快)的方式来做到这一点。 你说什么家伙?

回答

1

您可以创建一个与您的MyStringValues列表匹配的索引,并使用LINQ的Any进行查询。

你的指数将是这样的:

public class Devices_ByStringValue : AbstractIndexCreationTask<Device> 
{ 
    public override string IndexName => "Devices/ByStringValue"; 

    public Devices_ByStringValue() 
    { 
     Map = devices => from device in devices 
          select new { device.MyStringValues }; 
    } 
} 

现在你可以查询它想:

var devices = session.Query<Device>() 
     .Where(x => x.MyStringValues.Any(s => s == searchTerm)) 
     .ToList(); 

这是一个完整的控制台应用程序例如:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.Write("> Enter your search term: "); 

     var searchTerm = Console.ReadLine(); 

     using (var session = DocumentStoreHolder.Instance.OpenSession()) 
     { 
      var devices = session.Query<Device>() 
       .Where(x => x.MyStringValues.Any(s => s == searchTerm)) 
       .ToList(); 

      foreach (var device in devices) 
      { 
       Console.WriteLine(device.Id); 

       foreach (var s in device.MyStringValues) 
        Console.WriteLine($" - {s}"); 
      } 
     } 

     Console.ReadKey(); 
    } 
} 

public class Device 
{ 
    public Device() 
    { 
     MyStringValues = new List<string>(); 
    } 

    public string Id { get; set; } 
    public IList<string> MyStringValues { get; set; } 
} 

public class Devices_ByStringValue : AbstractIndexCreationTask<Device> 
{ 
    public override string IndexName => "Devices/ByStringValue"; 

    public Devices_ByStringValue() 
    { 
     Map = devices => from device in devices 
          select new { device.MyStringValues }; 
    } 
} 

public class DocumentStoreHolder 
{ 
    static DocumentStoreHolder() 
    { 
     Instance = new DocumentStore 
     { 
      Url = "http://localhost:8080/", 
      DefaultDatabase = "RavenTest", 
     }; 

     Instance.Initialize(); 
     Serializer = Instance.Conventions.CreateSerializer(); 
     Serializer.TypeNameHandling = TypeNameHandling.All; 

     Instance.Initialize(); 

     IndexCreation.CreateIndexes(typeof(Devices_ByStringValue).GetTypeInfo().Assembly, Instance); 
    } 

    public static DocumentStore Instance { get; } 

    public static JsonSerializer Serializer { get; } 
} 
0

创建一个包含来自MyStringValues的数据的索引。它可以在每个记录的数组中包含多个值。

然后,您可以创建索引查询,并使用.Where(x => x.MyStringValues.Contains(filteredValue))仅筛选包含给定值的记录。

然后使用流式传输(如果匹配记录的数量可能很高)或使用加载(您知道要加载的文档的上限)加载所有匹配的文档。

要测试演播室中的索引,可以使用简单的MyStringValues:abc查询来查询索引。

+0

thanx的答复!我必须诚实地说,我对RavenDB相当陌生。在这种情况下,你将如何创建一个静态索引? – Nicke

相关问题