2016-07-27 3 views
6

잘 작동하는 제안 사항을 제공해야하지만 문서의 다른 입력란을 통해 제안 사항을 필터링해야합니다.필터가있는 탄성 견적 제안

달성이 가능합니까? 내가 알아 낸 한, Elasticsearch는 이것을 할 수 없습니다. 어떤 대안 아이디어?

public async Task<ISuggestResponse> Suggest(string index, string projectId, string field, string text) 
     { 
      var suggestResponse = await _client.SuggestAsync<TDocument>(s => s 
                      .Index(index) 
                      .Completion("suggest", c => c 
                        .Text(text) 
                        .Context(con => con.Add("projectId", projectId)) 
                        .Field(field) 
                        .Size(20) 
                       ) 
                    ); 

     return suggestResponse; 
    } 

----------- 업데이트 --------------------

ElasticsearchConfig.cs

client.Map<Component>(d => d 
     .Properties(props => props 
      .String(s => s 
       .Name("name")) 
      .Completion(c => c 
       .Name("componentSuggestion") 
       .Analyzer("simple") 
       .SearchAnalyzer("simple") 
       .Context(context => context 
        .Category("projectId", cat => cat 
        .Field(field => field.ProjectId))) 
       .Payloads())) 
     .Properties(props => props.String(s => s.Name("id").NotAnalyzed())) 
     .Properties(props => props.String(s => s.Name("projectId").NotAnalyzed()))); 

답변

2

The Context Suggester

enter image description here

는 카테고리 또는 위치 정보에 기초하거나 필터링 요소를 제공하도록 완성 SUGGESTER을 연장한다. 이것은 자신의 목적에 충분할 수 있습니다.

취할 수도있는 대체 접근법은 컨텍스트 스승을 사용하여 검색 유형별 제안을 제공하고 완료 유형 매핑의 페이로드 내에 각 문서의 ID를 인덱싱하는 것입니다. 페이로드에서 반환 된 ID를 사용하여 문서를 검색하고이 시점에서 추가 필터링을 적용한 다음 필터링과 일치하는 문서 ID 만 반환합니다. 마지막으로이 문서 ID를 사용하여 원래 제안 응답에서 제안을 가져옵니다.

편집 :

여기에 상황에 맞는 SUGGESTER 작업의 완벽한 예

void Main() 
{ 
    var componentsIndex = "components"; 
    var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); 
    var settings = new ConnectionSettings(connectionPool) 
     // use component index when working with 
     // Component Poco type 
     .InferMappingFor<Component>(m => m 
      .IndexName(componentsIndex) 
     ); 

    var client = new ElasticClient(settings); 

    // make this example repeatable, so delete index if 
    // it already exists 
    if (client.IndexExists(componentsIndex).Exists) 
     client.DeleteIndex(componentsIndex); 

    // for example purposes, only use one shard and no replicas 
    // NOT RECOMMENDED FOR PRODUCTION 
    client.CreateIndex(componentsIndex, c => c 
     .Settings(s => s 
      .NumberOfShards(1) 
      .NumberOfReplicas(0) 
     ) 
    ); 

    client.Map<Component>(d => d 
     .Index(componentsIndex) 
     // infer mapping of fields from property of the POCO. 
     // This means we don't need to explicitly specify all 
     // mappings in .Properties() 
     .AutoMap() 
     // Now, override any inferred mappings from automapping 
     .Properties(props => props 
      .Completion(c => c 
       .Name(n => n.ComponentSuggestion) 
       .Context(context => context 
        .Category("projectId", cat => cat 
         .Field(field => field.ProjectId) 
        ) 
       ) 
       .Payloads() 
      ) 
      .String(s => s 
       .Name(n => n.Id) 
       .NotAnalyzed() 
      ) 
      .String(s => s 
       .Name(n => n.ProjectId) 
       .NotAnalyzed() 
      ) 
     ) 
    ); 

    var components = new[] { 
     new Component 
     { 
      Id = "1", 
      Name = "Component Name 1", 
      ComponentSuggestion = new CompletionField<object> 
      { 
       Input = new [] { "Component Name 1" }, 
       Output = "Component Name 1" 
      }, 
      ProjectId = "project_id" 
     }, 
     new Component 
     { 
      Id = "2", 
      Name = "Component Name 2", 
      ComponentSuggestion = new CompletionField<object> 
      { 
       Input = new [] { "Component Name 2" }, 
       Output = "Component Name 2" 
      }, 
      ProjectId = "project_id_2" 
     } 
    }; 

    // index some components with different project ids 
    client.IndexMany(components); 

    // refresh the index to make the newly indexed documents available for 
    // search. Useful for demo purposes but, 
    // TRY TO AVOID CALLING REFRESH IN PRODUCTION  
    client.Refresh(componentsIndex); 

    var projectId = "project_id"; 

    var suggestResponse = client.Suggest<Component>(s => s 
     .Index(componentsIndex) 
     .Completion("suggester", c => c 
      .Field(f => f.ComponentSuggestion) 
      .Text("Compon") 
      .Context(con => con.Add("projectId", projectId)) 
      .Size(20) 
     ) 
    ); 

    foreach (var suggestion in suggestResponse.Suggestions["suggester"].SelectMany(s => s.Options)) 
    { 
     Console.WriteLine(suggestion.Text); 
    } 
} 

public class Component 
{ 
    public string Id { get; set; } 

    public string Name { get; set; } 

    public string ProjectId { get; set; } 

    public CompletionField<object> ComponentSuggestion { get; set; } 
} 

이 수익률의 유일한 projectId의 문맥 대신 "project_id"

2

인을 기준으로 한 제안, Component Name 1, 완료 suggester의, 당신은 context suggester를 사용해야한다 그 목표는 추가 catego를 지정할 수 있도록 허용하는 것입니다. 귀하의 준법 수호자를위한 지역 또는 위치 정보 컨텍스트.

내가 잘못하지 않는다면, NEST는 Context 속성을 통해 작성된 질문에 문맥 수사자를 제공합니다.

public async Task<ISuggestResponse> Suggest(string index, string field, string text) 
    { 
     var suggestResponse = await _client.SuggestAsync<TDocument>(s => s 
       .Index(index) 
       .Completion("suggest", c => c 
        .Text(text) 
        .Context(con => con.Add("your_field", "text")) 
        .Field(field) 
        .Size(20) 
      ) 
     ); 

     return suggestResponse; 
    } 

컨텍스트를 선언하려면 매핑의 완료 필드를 변경해야합니다.

+0

행운이 있나요? – Val

+0

나는 두렵습니다. 지금은 전혀 제안을 얻지 못하고 있습니다. –

+0

매핑하려는 내용을 [컨텍스트 지정] (https://www.elastic.co/guide/en/elasticsearch/reference/current/suggester-context.html#suggester-context-category)으로 변경 했습니까? 귀하의 검색어에 계정이 있습니까? – Val