2016-03-05 69 views
0

我尝试在elasticsearch中搜索用户。我有一个用户,“安迪”在索引中。当我搜索“gujjghjhgj”时,我从elasticsearch获得一位用户(Andy)。为什么?如果没有找到用户,则不返回任何内容。我怎样才能做到这一点?我有这个:使用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查询适用于NEST的新版本)踢和,因为现场没有一个值,该match查询不发出的部分的搜索请求。请求最终看起来像

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

与文件与UserNr 1返回。

要解决这个问题,您只需指定字段名称即可。下面是一个完整的示例

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。但是现在当我搜索“安迪”时,我得到了一位用户,但是当我搜索“An”或“And”时,我没有收到任何回应。为什么? :( – mrcode

+0

这是最好的问题:)作为一个单独的问题:)简而言之,这是因为'UserName'属性映射默认使用标准分析器,所以没有对输入运行'ngram'(或'edge ngram')分析。另外,'match'查询不会执行前缀匹配。为了解决这个问题,你可以使用'前缀查询',或者如果你希望做大量的前缀匹配,就更新映射来将'UserName'映射为一个'multi_field'并使用不同类型的分析,并重新索引你的文档。 –

+0

@mrcode请打开另一个问题,因为这个问题是一个新的,不同的问题。 –