2016-03-05 3 views
0

Я стараюсь искать пользователей в поиске elastics. У меня есть один пользователь, «Энди» в индексе. И когда я нахожусь на «gujjghjhgj», я получаю одного пользователя (Энди) обратно из elasticsearch. Зачем? Если ни один пользователь не был найден, ничего не возвращайте. Как я могу это сделать? У меня есть это:Поиск пользователей с elasticsearch

var ui = new UserInfo { UserName = "Andy", Name = "", UserNr = 1}; 
Client.CreateIndex("users"); 

Client.Update<UserInfo, UserInfo> 
       (DocumentPath<UserInfo> 
        .Id(ui.UserNr), descriptor => descriptor.Doc(ui).DocAsUpsert().Refresh() 
       ); 

var Result = Client.Search<UserInfo>(s => s 
      .Index("users") 
      .Query(q => q.Match(m => m.Query(name) 
      )) 
      .Size(pageSize) 
      .From((currentPage - 1)*pageSize)); 

unitItems = Result.Total; 
return Result.Documents.ToList(); 

[Serializable, ElasticsearchType(IdProperty = "UserNr")] 
public class UserInfo 
{ 
    public string UserName { get; set; } 
    public string Name { get; set; } 
    public string Avatar { get; set; } 
    public int UserNr { get; set; } 
} 
+0

Как выглядит отображение для 'UserInfo'? Является ли это явным образом определено или выведено? –

ответ

0

Проблема с поиском в том, что он не определяет поле для выполнения match запроса на; значение для выполнения соответствия с указанным, но не полем.

В этом случае NEST's conditionless query logic (примечание: это старая документация, но conditionless запросы относятся к более новым версиям НЕСТА) умирает, и потому, что поле не имеет значения, match запроса не излучаются как часть запроса поиска. Запрос заканчивает тем, как

POST http://localhost:9200/users/userinfo/_search 
{ 
    "from":0, 
    "size":10 
} 

с документом с 1 UserNr вернулся.

Чтобы исправить это, вам просто нужно указать имя поля. Вот полный пример для демонстрации

void Main() 
{ 
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); 
    var connectionSettings = new ConnectionSettings(pool) 
     // Disabling direct streaming and logging out requests and responses 
     // is useful during development, but may not want to do this 
     // in production as it has performance implications. 
     // Used here to write out requests and responses. 
     .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}"); 
       } 

       // 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"); 
       } 
      }) 
      .DefaultIndex("users"); 

    var client = new ElasticClient(connectionSettings); 

    var ui = new UserInfo { UserName = "Andy", Name = "", UserNr = 1 }; 

    if (!client.IndexExists("users").Exists) 
    { 
     client.CreateIndex("users"); 
    } 

    // can use index 
    client.Index(ui, descriptor => descriptor.Refresh()); 

    var pageSize = 10; 
    var currentPage = 1; 
    var name = "gujjghjhgj"; 

    var searchResponse = client.Search<UserInfo>(s => s 
     .Index("users") 
     .Query(q => q 
      .Match(m => m 
       // specify the field 
       .Field(f => f.UserName) 
       .Query(name)     
      ) 
     ) 
     .Size(pageSize) 
     .From((currentPage - 1) * pageSize) 
    ); 

    var total = searchResponse.Total; 
    var docs = searchResponse.Documents.ToList(); 
} 

[Serializable, ElasticsearchType(IdProperty = "UserNr")] 
public class UserInfo 
{ 
    public string UserName { get; set; } 
    public string Name { get; set; } 
    public string Avatar { get; set; } 
    public int UserNr { get; set; } 
} 
+0

Thanx. Но теперь, когда я ищу в «Энди», я получаю одного пользователя, НО, когда я ищу «А» или «И», я ничего не получаю. Зачем? :( – mrcode

+0

Это лучше всего задать как отдельный вопрос :) Короче говоря, это потому, что сопоставление свойств 'UserName' будет использовать стандартный анализатор по умолчанию, поэтому на входе не выполняется анализ' ngram' (или 'edge ngram'). Кроме того, запрос 'match' не будет выполнять сопоставление префикса. Чтобы решить проблему, вы можете использовать «префиксный запрос» или, если вы планируете выполнять много префиксных совпадений, обновите сопоставление для сопоставления 'UserName' как' multi_field' с различными различными типами анализа и переиндексируйте свои документы. –

+0

@mrcode Пожалуйста, откройте другой вопрос, так как этот вопрос является новым, другим вопросом. –

Смежные вопросы