2016-08-18 6 views
5

나는 다음과 같은 쿼리를 사용하여 탄성에 인덱스를 만든이 :ElasticSearch 둥지 삽입/업데이트

PUT public_site 
{ 
    "mappings": { 
    "page": { 
     "properties": { 
     "url": { 
      "type": "string" 
     }, 
     "title":{ 
      "type": "string" 
     }, 
     "body":{ 
      "type": "string" 
     }, 
     "meta_description":{ 
      "type": "string" 
     }, 
     "keywords":{ 
      "type": "string" 
     }, 
     "category":{ 
      "type": "string" 
     }, 
     "last_updated_date":{ 
      "type": "date" 
     }, 
     "source_id":{ 
     "type":"string" 
     } 
     } 
    } 
    } 
} 

I는 .NET NEST 라이브러리를 사용하여이 색인에 문서를 삽입하고 싶습니다. 내 문제는 .net 업데이트 메서드의 서명이 나에게 이해가되지 않는다는 것입니다.

client.Update<TDocument>(IUpdateRequest<TDocument,TPartialDocument>) 

자바 라이브러리가 나에게 너무 많은 의미합니다 : NEST에서

UpdateRequest updateRequest = new UpdateRequest(); 
updateRequest.index("index"); 
updateRequest.type("type"); 
updateRequest.id("1"); 
updateRequest.doc(jsonBuilder() 
     .startObject() 
      .field("gender", "male") 
     .endObject()); 
client.update(updateRequest).get(); 

TDocument 및 TPartialDocument 클래스에서 오는가? 인덱스를 나타내는 이러한 C# 클래스가 있습니까? 행하는 경우

답변

13

TDocumentTPartialDocument은 일반적인 유형

  • 가 Elasticsearch (TDocument)에서 문서를 나타내는 POCO 타입 파라미터
  • Elasticsearch에서 문서의 일부분의 표시 (TPartialDocument)이다 부분적인 갱신.

전체 업데이트의 경우 TDocumentTPartialDocument은 동일한 콘크리트 POCO 유형을 참조 할 수 있습니다. 시연 할 몇 가지 예를 살펴 보겠습니다.

위에서 정의한 매핑을 사용하여 색인을 만들어 보겠습니다. 둥지는 낙타 케이스 명명 규칙을 사용 POCO 속성을 직렬화 할 때 첫째로, 우리는 POCO 유형 기본적으로

public class Page 
{ 
    public string Url { get; set; } 

    public string Title { get; set; } 

    public string Body { get; set; } 

    [String(Name="meta_description")] 
    public string MetaDescription { get; set; } 

    public IList<string> Keywords { get; set; } 

    public string Category { get; set; } 

    [Date(Name="last_updated_date")] 
    public DateTimeOffset LastUpdatedDate { get; set; } 

    [String(Name="source_id")] 
    public string SourceId { get; set; } 
} 

를 사용하여 문서를 나타낼 수 있습니다. 색인에 일부 속성 (예 : "last_updated_date", NEST가 속성을 사용하여 이들을 직렬화하는 이름을 재정의 할 수 있습니다.

다음의 개발 동안 도움이되는 방식으로 구성되어

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); 
var pagesIndex = "pages"; 
var connectionSettings = new ConnectionSettings(pool) 
     .DefaultIndex(pagesIndex) 
     .PrettyJson() 
     .DisableDirectStreaming() 
     .OnRequestCompleted(response => 
      { 
       // log out the request 
       if (response.RequestBodyInBytes != null) 
       { 
        Console.WriteLine(
         $"{response.HttpMethod} {response.Uri} \n" + 
         $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}"); 
       } 
       else 
       { 
        Console.WriteLine($"{response.HttpMethod} {response.Uri}"); 
       } 

       Console.WriteLine(); 

       // log out the response 
       if (response.ResponseBodyInBytes != null) 
       { 
        Console.WriteLine($"Status: {response.HttpStatusCode}\n" + 
          $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" + 
          $"{new string('-', 30)}\n"); 
       } 
       else 
       { 
        Console.WriteLine($"Status: {response.HttpStatusCode}\n" + 
          $"{new string('-', 30)}\n"); 
       } 
      }); 

var client = new ElasticClient(connectionSettings); 

연결 설정에서 작동하도록 클라이언트를 만들 수 있습니다;

  1. DefaultIndex() - 기본 색인은 "pages"으로 구성되었습니다. 요청에 명시 적 인덱스 이름이 전달되지 않고 POCO에 대해 인덱스 이름을 유추 할 수없는 경우 기본 인덱스가 사용됩니다.
  2. PrettyJson() - json 요청 및 응답을 정교화 (들여 쓰기)합니다. 이것은 Elasticsearch와주고받는 내용을 확인하는 데 유용합니다.
  3. DisableDirectStreaming() - 기본적으로 NEST는 POCO를 요청 스트림으로 직렬화하고 응답 스트림에서 응답 유형을 deserialize합니다. 이 직접 스트리밍을 비활성화하면 요청 및 응답 바이트가 메모리 스트림에 버퍼되므로 우리가 로그 아웃 할 수 있습니다. OnRequestCompleted()
  4. OnRequestCompleted() - 응답을받은 후에 호출됩니다. 이를 통해 우리는 개발 중에 요청과 응답을 로그 아웃 할 수 있습니다.

2, 3 및 4는 개발 중에 유용하지만 성능상의 오버 헤드가 있으므로 프로덕션 환경에서 사용하지 않기로 결정할 수 있습니다.

이제

,의 새로운 페이지 유형 색인 페이지 매핑

// delete the index if it exists. Useful for demo purposes so that 
// we can re-run this example. 
if (client.IndexExists(pagesIndex).Exists) 
    client.DeleteIndex(pagesIndex); 

// create the index, adding the mapping for the Page type to the index 
// at the same time. Automap() will infer the mapping from the POCO 
var createIndexResponse = client.CreateIndex(pagesIndex, c => c 
    .Mappings(m => m 
     .Map<Page>(p => p 
      .AutoMap() 
     ) 
    ) 
); 

Take a look at the automapping documentation for more details around how you can control mapping for POCO types

으로 인덱스를 생성한다 수 있도록 간단한 문서의 경우를 만듭니다 문서를 색인

// create a sample Page 
var page = new Page 
{ 
    Title = "Sample Page", 
    Body = "Sample Body", 
    Category = "sample", 
    Keywords = new List<string> 
    { 
     "sample", 
     "example", 
     "demo" 
    }, 
    LastUpdatedDate = DateTime.UtcNow, 
    MetaDescription = "Sample meta description", 
    SourceId = "1", 
    Url = "/pages/sample-page" 
}; 

// index the sample Page into Elasticsearch. 
// NEST will infer the document type (_type) from the POCO type, 
// by default it will camel case the POCO type name 
var indexResponse = client.Index(page); 

로 존재하지 않거나 존재하는 문서를 덮어 씁니다. Elasticsearch has optimistic concurrency control은 다른 조건에서 이것이 어떻게 작동하는지 제어하는 ​​데 사용할 수 있습니다.

Update 방법을 사용하여 문서를 업데이트 할 수 있지만 약간의 배경이 있습니다.

색인, 유형 및 ID를 지정하여 Elasticsearch에서 문서를 가져올 수 있습니다. NEST는 POCO에서이 모든 것을 추론 할 수 있기 때문에 약간 더 쉽게 만듭니다. 매핑을 만들 때 POCO에 Id 속성을 지정하지 않았습니다. NESTId이라는 속성이있는 경우이 속성을 문서의 ID로 사용하지만 Elasticsearch에서 문서의 ID를 생성하여 문서 메타 데이터에 넣으면 문제가되지 않으므로 문제가되지 않습니다. 그러나 문서 메타 데이터가 원본 문서와 분리되어 있기 때문에 POCO 형식의 모델링 문서를 약간 까다 롭지만 불가능한 것은 아닙니다. 주어진 응답에 대해 메타 데이터를 통해 문서의 ID에 액세스하고 _source 필드를 통해 출처에 액세스 할 수 있습니다. ID를 애플리케이션의 소스와 결합 할 수 있습니다.

쉽게 해결할 수있는 방법은 POCO에 ID가 있어야합니다. POCO에 Id 속성을 지정할 수 있으며이 값은 문서의 ID로 사용되지만, 원하지 않으면 Id 속성을 호출 할 필요가 없습니다. 그렇지 않으면 우리는 NEST 속성은 ID를 나타냅니다. 이것은 속성으로 할 수 있습니다. SourceIdPage 인스턴스의 고유 ID라고 가정하면 ElasticsearchTypeAttributeIdProperty 속성을 사용하여 지정합니다. 어쩌면 우리는이 문자열을 분석하지 않아야하지만 인덱스는 그대로, 우리는 또한 장소에이 가진 재산

[ElasticsearchType(IdProperty = nameof(SourceId))] 
public class Page 
{ 
    public string Url { get; set; } 

    public string Title { get; set; } 

    public string Body { get; set; } 

    [String(Name="meta_description")] 
    public string MetaDescription { get; set; } 

    public IList<string> Keywords { get; set; } 

    public string Category { get; set; } 

    [Date(Name="last_updated_date")] 
    public DateTimeOffset LastUpdatedDate { get; set; } 

    [String(Name="source_id", Index=FieldIndexOption.NotAnalyzed)] 
    public string SourceId { get; set; } 
} 

에 속성의 Index 속성을 통해이를 제어 할 수 있습니다, 우리는 이전과 인덱스를 다시 작성해야합니다 따라서 이러한 변경 사항은 매핑에 반영되고 NEST는 Page 인스턴스를 인덱싱 할 때이 구성을 사용할 수 있습니다.

이제

, 다시 업데이 트 : 우리는 첫 번째 인수는 우리가 얻고 싶은 문서의 ID입니다 색인을 다시 그것을

var getResponse = client.Get<Page>("1"); 

var page = getResponse.Source; 

// update the last updated date 
page.LastUpdatedDate = DateTime.UtcNow; 

var updateResponse = client.Update<Page>(page, u => u.Doc(page)); 

을 한 후, Elasticsearch에서 문서를 얻을 응용 프로그램을 업데이트 할 수 있습니다 이는 Page 인스턴스에서 NEST에 의해 추론 할 수 있습니다.우리가

var indexResponse = client.Index(page); 

그러나 모든 필드를 업데이트되기 때문에 우리는 단지 LastUpdatedDate를 업데이트 할 때문에 우리가 여기에 전체 문서를 전달하고 있기 때문에, 우리는 그냥 가져 가진, 대신 Update().Index()을 사용할 수도 Elasticsearch의 문서를 응용 프로그램에서 업데이트 한 다음 Elasticsearch로 다시 보내려면 많은 작업이 필요합니다. 업데이트 된 LastUpdatedDate부분 문서 대신 Elasticsearch에 보내면됩니다. C#을 익명의 유형 우리는 부분적인 업데이트를 RetryOnConflict(int)

var partialUpdateResponse = client.Update<Page, object>("1", u => u 
    .Doc(lastUpdatedDate) 
    .RetryOnConflict(1) 
); 

를 사용하여 여기에 우리가 필요로하는 경우 낙관적 동시성 제어를 사용할 수 있습니다 여기에

// model our partial document with an anonymous type. 
// Note that we need to use the snake casing name 
// (NEST will still camel case the property names but this 
// doesn't help us here) 
var lastUpdatedDate = new 
{ 
    last_updated_date = DateTime.UtcNow 
}; 

// do the partial update. 
// Page is TDocument, object is TPartialDocument 
var partialUpdateResponse = client.Update<Page, object>("1", u => u 
    .Doc(lastUpdatedDate) 
); 

정말 유용 Elasticsearch는 문서를 얻을 부분 업데이트를 적용 할 것 업데이트 된 문서의 색인을 생성합니다. 문서가 가져 오기와 업데이트 사이에서 변경된 경우 Elasticsearch가 RetryOnConflict(1)을 기반으로 한 번 더 다시 시도 할 것입니다.

도움이 되길 바랍니다. :)

+1

좋은 대답이며 설명은 분명합니다. – Chan