2016-12-21 5 views
0

왜 이것이 작동하지 않을지 생각할 수 있습니까? 기본적으로 soundex 분석기를 사용하여 색인을 생성하는 두 개의 필드가 있습니다. 아래의 구성을 참조하십시오. 그러나 인덱스에 저장된 이름과 비슷한 이름을 사용하여 검색하면 작동하지 않습니다.탄성 검색 Soundex 일치 검색어 - NEST

anz.Custom("soundex_analyzer", dma => dma 
        .Tokenizer("keyword") 
        .Filters("lowercase", "icu_folding", "soundex_filter")); 


tk.Phonetic("soundex_filter", ph => ph.Encoder(PhoneticEncoder.RefinedSoundex).Replace(false)); 

[String(Name = "surnameSoundex", Index = FieldIndexOption.Analyzed, Analyzer = "soundex_analyzer")] 
public string SurnameSoundex { get; set; } 

[String(Name = "forenameSoundex", Index = FieldIndexOption.Analyzed, Analyzer = "soundex_analyzer")] 
public string ForenameSoundex { get; set; } 


if (string.IsNullOrEmpty(oReq.person.ForenameSoundex) || oReq.person.ForenameSoundex.Length < 3) 
    { 
    _qc = _qd.Match(mt => mt.Field(fld => fld.SurnameSoundex).Query(oReq.person.SurnameSoundex)); 
    _AndQueries.Add(_qc); 
    _qc = null; 
    } 
    else 
    { 
     //search on surname and combination of forename and surname 
     _qc = _qd.Match(mt => mt.Field(fld => fld.SurnameSoundex).Query(oReq.person.SurnameSoundex)) 
         || _qd.Match(mt => mt.Field(fld => fld.SurnameSoundex).Query(oReq.person.SurnameSoundex)) 
         && _qd.Match(mt => mt.Field(fld => fld.ForenameSoundex).Query(oReq.person.ForenameSoundex)); 
     _AndQueries.Add(_qc); 
     _qc = null; 
     } 

나는이 문제를 확인했지만, 기본적으로 그 쿼리가 쿼리 컨테이너 목록에 전달 할 수는 부울 쿼리에 전달 배열로 전환 될 때 쿼리의 건설에 아무런 잘못이 없습니다.

키워드 분석기와 함께 키워드 토크 나이저를 사용할 수 없는지 확실하지 않았습니다.

미리 감사드립니다.

은 편집 :

그래서 기본적으로 내가 마시고있는 사람 클래스가 정의 속성 :

[ElasticsearchType(Name = "person", IdProperty = "id")] 
public class Person 
{ 
    [String(Name = "id", Index = FieldIndexOption.NotAnalyzed)] 
    public string id { get; set; } 

    [String(Name = "forename", Index = FieldIndexOption.Analyzed, Analyzer = "low_whit_analyzer", SearchAnalyzer = "low_whit_analyzer")] 
    public string forename { get; set; } 

    [String(Name = "forenameSoundex", Index = FieldIndexOption.Analyzed, Analyzer = "soundex_analyzer", SearchAnalyzer = "soundex_analyzer")] 
    public string forenameSoundex { get; set; } 

    [String(Name = "surname", Index = FieldIndexOption.Analyzed, Analyzer = "low_whit_analyzer", SearchAnalyzer = "low_whit_analyzer")] 
    public string surname { get; set; } 

    [String(Name = "surnameSoundex", Index = FieldIndexOption.Analyzed, Analyzer = "soundex_analyzer", SearchAnalyzer = "soundex_analyzer")] 
    public string surnameSoundex { get; set; } 

    [Date(Name = "dob", Index = NonStringIndexOption.NotAnalyzed, Format = "date_optional_time")] 
    public DateTime dob { get; set; } 

    [String(Name = "postCode1", Index = FieldIndexOption.Analyzed, Analyzer = "keyword_analyzer", NullValue = null)] 
    public string postCode1 { get; set; } 

    [String(Name = "postCode2", Index = FieldIndexOption.Analyzed, Analyzer = "keyword_analyzer", NullValue = null)] 
    public string postCode2 { get; set; } 

    [String(Name = "identifier", Index = FieldIndexOption.Analyzed, Analyzer = "low_whit_analyzer", NullValue = null)] 
    public string identifier { get; set; } 

    [String(Name = "email", Index = FieldIndexOption.Analyzed, Analyzer = "keyword_analyzer", NullValue = null)] 
    public string email { get; set; } 

    [String(Name = "mobile", Index = FieldIndexOption.Analyzed, Analyzer = "low_whit_analyzer", NullValue = null)] 
    public string mobile { get; set; } 

    [String(Name = "gender", Index = FieldIndexOption.Analyzed, Analyzer = "keyword_analyzer")] 
    public string gender { get; set; } 

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

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

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

    [String(Name = "personalReferenceId", Index = FieldIndexOption.Analyzed, Analyzer = "low_whit_analyzer")] 
    public string personalReferenceId { get; set; } 
} 
내가 다음 코드를 사용하여 인덱스를 생성

: 다음 사용

Uri eSAddress = new Uri(ConfigurationManager.AppSettings["ElasticSearchUrl"]); 
     _clientSettings = new ConnectionSettings(eSAddress) 
      .MapDefaultTypeIndices(i => i.Add(typeof(Person), "people")); 
     _client = new ElasticClient(_clientSettings); 

     var oRequest = new IndexExistsRequest("people"); 
     var bIndexExists = _client.IndexExists(oRequest); 

     if (bIndexExists.Exists == false) 
     { 
      var oIndexResponse = _client.CreateIndex("people", c => c 
      .Settings(st => st 
       .RefreshInterval(-1) 
       .Translog((ts) => SetupTranslogSettings(ts)) 
       .NumberOfShards(1) 
       .NumberOfReplicas(0) 
        .Analysis(an => an 
         .TokenFilters((tf) => SetUpFilters(tf)) 
         .Analyzers((anz) => SetUpAnalyzers(anz) 
       ))) 
       .Mappings(mp => mp.Map<Person>(m => m 
       .AutoMap() 
       .AllField(al => al.Enabled(false))))); 

을 logstash를 사용하여 다음 구성을 사용하여 데이터베이스에서 내 레코드를 가져옵니다.

statement => "SELECT IGF_UID AS id, IGF_FORENAME AS forename, IGF_SURNAME AS surname, IGF_FORENAME AS forenameSoundex, IGF_SURNAME AS surnameSoundex, 
       IGF_DATE_OF_BIRTH AS dob, IGF_POSTCODE1 AS postCode1, IGF_POSTCODE2 AS postCode2, IGF_NHS_NUMBER AS identifier, IGF_EMAIL AS email, 
       IGF_MOBILE AS mobile, (CASE IGF_SEX 
         WHEN 'male' THEN 'm' 
         WHEN 'female' THEN 'f' 
         WHEN 'transgender' THEN 't' 
         WHEN 'unknown' THEN 'u' 
         WHEN '' THEN NULL 
         ELSE IGF_SEX 
         END) AS gender, IGF_ADDRESS1 AS address1, IGF_ADDRESS2 AS address2 FROM dbo.IGT_PEOPLE" 
    } 
} 
    filter { 
    mutate { 
    remove_field => [ "@timestamp", "@version" ] 
    } 
    } 

output { 
elasticsearch { 
    hosts => "localhost" 
    index => "people" 
    document_type => "person" 
    document_id => "%{id}" 
    manage_template => false 
    template_overwrite => false 
    } 
} 

내 분석기는 아래에 포함되어 있습니다 - 나는 이중 메타 폰 토큰 필터 변경 참고 :

public static void AddSoundexAnalyzer(ref AnalyzersDescriptor anz) 
    { 
     anz.Custom("soundex_analyzer", dma => dma 
        .Tokenizer("keyword") 
        .Filters("soundex_filter")); 
    } 

public static void AddSoundexFilter(ref TokenFiltersDescriptor tk) 
    { 
     tk.Phonetic("soundex_filter", ph => ph.Encoder(PhoneticEncoder.DoubleMetaphone).Replace(true)); 
    } 

은 그 때 나는 너무 적어도 하나의 쿼리와 일치해야한다 꼭 내에서 쿼리와 부울 쿼리를 사용하여 쿼리합니다.

public SearchDescriptor<Person> FuzzySearch(PersonSearchRequest oReq) 
    { 
     var oPerson = oReq.person; 
     var oSearchParams = oReq.searchParams; 
     _s = new SearchDescriptor<Person>(); 
     _b = new BoolQueryDescriptor<Person>(); 
     _AndQueries = new List<QueryContainer>(); 
     _OrQueries = new List<QueryContainer>(); 

     GetNameSearchClauses(oReq, ref _OrQueries, ref _AndQueries); 

     if (_OrQueries.Count > 0 || _AndQueries.Count > 0) 
     { 
      _b.Should(_OrQueries.ToArray()); 
      _b.Must(_AndQueries.ToArray()); 
      return _s.Query(qu => qu.Bool((z) => _b)).Sort(srt => srt.Descending(SortSpecialField.Score)); 
     } 
     else 
     { 
      return null; 
     } 
    } 

그런 다음 내 forenameSoundex 및 surnameSoundex 쿼리는 다음과 같은 방법으로 구성되어 있습니다

public void GetNameSearchClauses(PersonSearchRequest oReq, ref List<QueryContainer> _OrQueries, ref List<QueryContainer> _AndQueries) 
    { 
     if (oReq.searchParams.useSoundex == true && oReq.person.surnameSoundex.Length > 3)//use different analyzers 
     { 
      if (!string.IsNullOrEmpty(oReq.person.surnameSoundex)) 
      {//check if clause is null 

       //if no first name then just search on surname 
       if (string.IsNullOrEmpty(oReq.person.forenameSoundex) || oReq.person.forenameSoundex.Length < 3) 
       { 
        _qc = _qd.Match(mt => mt.Field(fld => fld.surnameSoundex).Query(oReq.person.surnameSoundex)); 
        _AndQueries.Add(_qc); 
        _qc = null; 
       } 
       else 
       { 
        //search on surname and combination of forename and surname 
        _qc = _qd.Match(mt => mt.Field(fld => fld.surnameSoundex).Query(oReq.person.surnameSoundex)) 
         || _qd.Match(mt => mt.Field(fld => fld.surnameSoundex).Query(oReq.person.surnameSoundex)) 
         && _qd.Match(mt => mt.Field(fld => fld.forenameSoundex).Query(oReq.person.forenameSoundex)); 
        _AndQueries.Add(_qc); 
        _qc = null; 
       } 
      } 
     } 

}

+0

의 차이는 내 elasticsearch 지수에 내가 logstash에서 수입 기록을 분석하거나 올바르게 분석하지만되지 않는다는 것입니다 내 API를 통해 레코드를 추가하는 경우 soundex 작품. 왜 아직 확실하지 않습니다. – GSkidmore

+0

작은 재현 가능한 예를 제공해 주시겠습니까? 위의 내용은 응용 프로그램의 여러 부분에서 발췌 한 것처럼 보이므로 모든 사람이 답변을 제공하는 데 어려움이 있습니다. –

+0

그래요, 불행히도 코드가 솔루션에서 많이 나뉘어졌습니다. 나는 더 간결한 세부 사항을 제공하려고 노력했다. – GSkidmore

답변

1

문제는 logstash의 JDBC 플러그인을 사용하여 자동으로 열 이름을 lowercases이었다. 그래서 내 SQL 문 내에서 별칭을 생성하여 elasticsearch 필드 이름에 직접 매핑하면 logstash를 통과 할 때 소문자로 변환됩니다.

내 JDBC 설정은 다음 줄 필요 : lowercase_column_names => 거짓

관련 문제