2016-09-19 49 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

相關問題