2015-02-10 75 views
4

我已經得到了一個數據庫,該數據庫可以與基本的CRUD操作相對應。這很快通過使用.NET 4.5/MVC5和EF6完成。這意味着數據庫優先方法。Nest無法應對EF6/MVC5的大型數據庫模型

新要求:(彈性)搜索。

當爲自定義類創建索引(未鏈接到模型中的其他類)時,一切正常。當我使用有很多外鍵的類時,事情就停止了。該數據庫由100個表格和400多個外鍵組成。

我認爲這個問題可能是循環引用(客戶有n個合同,它有一個客戶的參考,它有一個合同列表,...你得到的圖片)。最終我得到一個OutOfMemory異常,一切都崩潰了。

代碼:

public static Uri node; 
public static ConnectionSettings settings; 
public static ElasticClient client; 

public ActionResult TestIndex() 
    { 
     node = new Uri("http://localhost:9200"); 
     settings = new ConnectionSettings(node, defaultIndex: "crudapp"); 
     client = new ElasticClient(settings); 

     var indexSettings = new IndexSettings(); 
     indexSettings.NumberOfReplicas = 1; 
     indexSettings.NumberOfShards = 1; 

     //The next line causes the OutOfMemoryException 
     client.CreateIndex(c => c.Index("crudapp") 
           .InitializeUsing(indexSettings) 
           .AddMapping<Customer>(map => map.MapFromAttributes(maxRecursion: 1))); 


     foreach (Customer c in db.Customer.Where(a => a.Active == true)) 
      client.Index(c); 

     return View("Index"); 
    } 

我怎麼能告訴巢停止遞歸或不使用特定的對象?

樣品類:

public partial class Customer 
    { 
     public Customer() 
     { 
      this.CustomerContract = new HashSet<CustomerContract>(); 
     } 

     public int Customerid { get; set; } 
     public string CustomerName { get; set; } 
     public string Description { get; set; } 
     public bool Active { get; set; } 

     public virtual ICollection<CustomerContract> CustomerContract { get; set; } 
    } 

    public partial class CustomerContract 
    { 
     public CustomerContract() 
     { 
      this.Host = new HashSet<Host>(); 
     } 

     public int CustomerContractid { get; set; } 
     public string CustomerContractName { get; set; } 
     public string Description { get; set; } 
     public int CustomerID { get; set; } 
     public bool Active { get; set; } 

     public virtual Customer Customer { get; set; } 
     public virtual ICollection<Host> Host { get; set; } 
    } 

回答

2

OutOfMemoryException幾乎可以肯定是從你Customer對象的JSON序列化的到來。因此,這個問題不是NEST或Elasticsearch功能之一,而是JSON.NET功能之一。

您可以處理這兩種方式之一:通過JSON.NET筆者

1.序列化大對象選擇性

This article討論了減少對象的大小。您可能會提供JsonIgnoreAttribute property屬性來指示序列化程序忽略某些屬性。或者一個IContractResolver的實現可能對EF對象的定義影響較小(特別是考慮到它們是數據庫優先生成的),但我不確定這是否可以與JSON.NET上的NEST依賴關係一起使用。

如果您沒有處理NEST對JSON.NET依賴性的選項,您總是可以找到另一種方式來序列化對象,並通過使用Elasticsearch.NET語法而不是NEST(「基本上構建Elasticsearch.NET的頂層)。因此,不要致電ElasticClient.Index(..),撥打電話ElasticClient.Raw.Index(..),其中body參數是您希望索引的對象的JSON字符串表示(您自己的構造)。

2.項目大對象到一個較小的數據傳輸對象,而不是一個索引對象Customer,地圖只有你想的屬性索引到的數據傳輸對象(DTO)靶向您Elasticsearch架構

/文件類型。

foreach (Customer c in db.Customer.Where(a => a.Active == true)) 
    client.Index(new MyElasticsearchTypes.Customer() 
     { 
      CustomerId = c.CustomerId, 
      CustomerName = c.CustomerName, 
      Description = c.Description 
     }); 

在C#中,你有很多的選項,如何處理這樣的DTO的創作,包括:

  1. 顯式類型與手動映射(像我的例子)對象。
  2. 使用映射工具(如AutoMapper)顯式鍵入對象。
  3. 動態對象。

扁平設計

注意,使用Elasticsearch不是簡單地拋出你的數據變成「索引」的情況下。您需要從「文檔」的角度開始思考,並試圖從您的關係數據庫中索引數據時對其意義。 Elasticsearch指南文章Data In, Data Out是開始閱讀的好地方。另一種叫Managing relations inside Elasticsearch文章是根據您的情況尤其重要:

在它的心臟,Elasticsearch是一個平面層次結構,並試圖迫使關係數據轉化成它可以是非常具有挑戰性的。有時候,最好的解決方案是明智地選擇哪些數據去標準化,以及在哪裏可以接受第二個查詢兒童的查詢