2016-02-11 41 views
6

我似乎無法獲得NEST 2.0中多字段映射的語法正確性 - 如果這是正確的術語。我爲映射找到的每個示例似乎都是< = NEST的1.x版本。我是Elasticsearch和NEST的新手,我一直在閱讀他們的文檔,但NEST文檔尚未針對2.x完全更新。使用NEST 2.x創建具有多字段映射語法的索引

基本上,我不需要索引或存儲整個類型。有些字段僅用於建立索引,有些字段需要索引和檢索,有些字段不需要索引,僅用於檢索。

MyType 
{ 
    // Index this & allow for retrieval. 
    int Id { get; set; } 

    // Index this & allow for retrieval. 
    // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens. 
    string CompanyName { get; set; } 

    // Don't index this for searching, but do store for display. 
    DateTime CreatedDate { get; set; } 

    // Index this for searching BUT NOT for retrieval/displaying. 
    string CompanyDescription { get; set; } 

    // Nest this. 
    List<MyChildType> Locations { get; set; } 
} 

MyChildType 
{ 
    // Index this & allow for retrieval. 
    string LocationName { get; set; } 

    // etc. other properties. 
} 

我已經能夠索引整個對象和孩子一樣,用作爲一個例子如下:

client.Index(item, i => i.Index(indexName)); 

然而,實際的對象比這個更大的不少,我真的不需要它。我發現這看起來像我想我想做的,但在一箇舊版本:multi field mapping elasticsearch

我認爲「映射」是我要去的,但就像我說的,我是新的到Elasticsearch和NEST,我正在嘗試學習術語。

溫柔! :)這是我第一次對SO提出問題。謝謝!

回答

0

我想你至少有2種可能性,以解決您的問題:

  1. 在索引:創建類似元數據模型,它只是用於檢索存儲。請參閱_source field以限制返回此字段。
  2. 關於搜索:指定要查詢的字段:如果您不想查詢CreatedDate,只是不要將其包含在搜索中。

在我來說,我使用這兩種方法來獲得非常快的結果:-)

6

據我所看到的,你沒有任何複雜的類型,您正試圖地圖。所以你可以很容易地使用NEST屬性來映射你的對象。

檢查了這一點:

[Nest.ElasticsearchType] 
public class MyType 
{ 
    // Index this & allow for retrieval. 
    [Nest.Number(Store=true)] 
    int Id { get; set; } 

    // Index this & allow for retrieval. 
    // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens. 
    [Nest.String(Store = true, Index=Nest.FieldIndexOption.Analyzed, TermVector=Nest.TermVectorOption.WithPositionsOffsets)] 
    string CompanyName { get; set; } 

    // Don't index this for searching, but do store for display. 
    [Nest.Date(Store=true, Index=Nest.NonStringIndexOption.No)] 
    DateTime CreatedDate { get; set; } 

    // Index this for searching BUT NOT for retrieval/displaying. 
    [Nest.String(Store=false, Index=Nest.FieldIndexOption.Analyzed)] 
    string CompanyDescription { get; set; } 

    [Nest.Nested(Store=true, IncludeInAll=true)] 
    // Nest this. 
    List<MyChildType> Locations { get; set; } 
} 

[Nest.ElasticsearchType] 
public class MyChildType 
{ 
    // Index this & allow for retrieval. 
    [Nest.String(Store=true, Index = Nest.FieldIndexOption.Analyzed)] 
    string LocationName { get; set; } 

    // etc. other properties. 
} 

在此聲明之後,創建此映射elasticsearch你需要做類似的電話:

var mappingResponse = elasticClient.Map<MyType>(m => m.AutoMap()); 

隨着自動映射()調用NEST將讀取你的來自您的POCO的屬性並相應地創建映射請求。

另請參閱here中的「基於屬性的映射」部分。

乾杯!

3

在撰寫本文時,Nest沒有提供將類中的屬性映射到使用內置屬性的文檔映射中的多個字段的方法。但是,它確實提供了對映射進行任何操作所需的設施,如果您自己編寫JSON,則可以執行此操作。

以下是我爲滿足自己的需要而設計的解決方案。無論您需要做什麼,都不應該很難將其作爲起點。

首先,這裏我要生成

{ 
    "product":{ 
     "properties":{ 
     "name":{ 
      "type":"string", 
      "index":"not_analyzed", 
      "fields":{ 
       "standard":{ 
        "type":"string", 
        "analyzer":"standard" 
       } 
      } 
     } 
     } 
    } 
} 

product文件將隨後有name場,這是索引,但沒有分析的映射,以及name.standard領域,它使用標準分析器的例子。

的C#類,我生成這個樣子的

[ElasticsearchType] 
public class Product 
{ 
    [WantsStandardAnalysisField] 
    public string Name { get; set; } 
} 

注意WantsStandardAnalysisField屬性的映射。這是一個沒有添加特殊屬性的自定義屬性。真的只是:

public class WantsStandardAnalysisField : Attribute {} 

如果我使用自動映射原來的樣子,我的自定義屬性會被忽略,我會得到具有name領域的映射關係,而不是name.standard。幸運的是,AutoMap接受IPropertyVisitor的實例。一個名爲NoopPropertyVisitor的基類實現了這個接口並且什麼也不做,所以你可以繼承它並且只覆蓋你關心的方法。當您將屬性訪問者與AutoMap一起使用時,它將爲您生成文檔映射,但在發送給Elastic Search之前給您一個修改它的機會。我們所需要做的就是查找標有我們的自定義屬性的屬性,併爲它們添加一個字段。

這裏,做一個例子:

public class ProductPropertyVisitor : NoopPropertyVisitor 
{ 
    public override void Visit(IStringProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) 
    { 
     base.Visit(type, propertyInfo, attribute); 

     var wsaf = propertyInfo.GetCustomAttribute<WantsStandardAnalysisField>(); 
     if (wsaf != null) 
     { 
      type.Index = FieldIndexOption.NotAnalyzed; 
      type.Fields = new Properties 
      { 
       { 
        "standard", 
        new StringProperty 
        { 
         Index = FieldIndexOption.Analyzed, 
         Analyzer = "standard" 
        } 
       } 
      }; 
     } 
    } 
} 

正如你所看到的,我們可以做很多事情,我們想用生成的屬性,包括關閉分析的主要性能和增加新的字段它自己的設置。爲了好玩,您可以將一些屬性添加到自定義屬性中,以便指定所需字段的名稱和分析器的名稱。您甚至可以修改代碼以查看該屬性是否已多次添加,從而可以根據需要添加任意數量的字段。

如果你是通過產生使用自動映射,如映射,任何方法來運行這個:

new TypeMappingDescriptor<Product>().AutoMap(new ProductPropertyVisitor()) 

你會得到想要的多領域的映射。現在您可以自定義映射到您的心臟的內容。請享用!

5

除了Colin'sSelçuk's的答案,您還可以完全控制通過流暢(和對象初始值設定語法)映射API的映射。以下是根據您的要求

void Main() 
{ 
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); 
    var connectionSettings = new ConnectionSettings(pool); 

    var client = new ElasticClient(connectionSettings); 

    client.Map<MyType>(m => m 
     .Index("index-name") 
     .AutoMap() 
     .Properties(p => p 
      .String(s => s 
       .Name(n => n.CompanyName) 
       .Fields(f => f 
        .String(ss => ss 
         .Name("raw") 
         .NotAnalyzed() 
        ) 
       ) 
      ) 
      .Date(d => d 
       .Name(n => n.CreatedDate) 
       .Index(NonStringIndexOption.No)   
      ) 
      .String(s => s 
       .Name(n => n.CompanyDescription) 
       .Store(false) 
      ) 
      .Nested<MyChildType>(n => n 
       .Name(nn => nn.Locations.First()) 
       .AutoMap() 
       .Properties(pp => pp 
        /* properties of MyChildType */ 
       ) 
      ) 
     ) 
    ); 
} 

public class MyType 
{ 
    // Index this & allow for retrieval. 
    public int Id { get; set; } 

    // Index this & allow for retrieval. 
    // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens. 
    public string CompanyName { get; set; } 

    // Don't index this for searching, but do store for display. 
    public DateTime CreatedDate { get; set; } 

    // Index this for searching BUT NOT for retrieval/displaying. 
    public string CompanyDescription { get; set; } 

    // Nest this. 
    public List<MyChildType> Locations { get; set; } 
} 

public class MyChildType 
{ 
    // Index this & allow for retrieval. 
    public string LocationName { get; set; } 

    // etc. other properties. 
} 

一個例子這將產生映射

{ 
    "properties": { 
    "id": { 
     "type": "integer" 
    }, 
    "companyName": { 
     "type": "string", 
     "fields": { 
     "raw": { 
      "type": "string", 
      "index": "not_analyzed" 
     } 
     } 
    }, 
    "createdDate": { 
     "type": "date", 
     "index": "no" 
    }, 
    "companyDescription": { 
     "type": "string", 
     "store": false 
    }, 
    "locations": { 
     "type": "nested", 
     "properties": { 
     "locationName": { 
      "type": "string" 
     } 
     } 
    } 
    } 
} 

調用.AutoMap()原因NEST來推斷基於物業類型的映射,並應用到他們的任何屬性。然後.Properties()覆蓋任何推斷的映射。例如

  • CompanyName被映射爲一個multi_field與現場companyName使用標準分析器和companyName.raw未分析進行分析。您可以使用.Field(f => f.CompanyName.Suffix("raw"))
  • Locations映射爲nested類型(默認情況下,自動映射將推斷爲object類型映射)。然後您可以在Nested<MyChildType>()調用中使用.Properties()定義MyChildType的任何特定映射。
+0

真的很好的答案。似乎主要是爲我工作,但是,我在Nest 2.4.2中使用'.Suffix(「raw」)'有一個問題(它只是不起作用)。我最後使用了'+「.raw」'。 – Harvey