0

I try to search for users in elasticsearch. I have one user, "Andy" in the index. And when i search on "gujjghjhgj" i get one user(Andy) back from elasticsearch. Why? If no user was found, return nothing. How can i do this? I have this:

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; }
}
1
  • What does the mapping for UserInfo look like? Is it explicitly defined or inferred? Commented Mar 5, 2016 at 23:02

1 Answer 1

0

The problem with your search is that it does not specify a field to perform the match query on; the value to perform a match with is specified but not the field.

In this scenario, NEST's conditionless query logic (note: this is old documentation, but conditionless queries apply to newer versions of NEST) kicks in and because field does not have a value, the match query is not emitted as part of the search request. The request ends up looking like

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

with the document with UserNr 1 returned.

To fix this, you just need to specify the field name. Here's a complete example to demonstrate

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; }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanx. But now when i search on "Andy" i get one user back, BUT when i search on "An" or "And" i get nothing back. Why? :(
That's best asked as a separate question :) In short, it's because the UserName property mapping will be using the standard analyzer by default so no ngram (or edge ngram) analysis is run on the input. Additionally, the match query will not perform prefix matching. To resolve, you can use a prefix query or, if you expect to do a lot of prefix matches, update the mapping to map UserName as a multi_field with different different types of analysis, and reindex your documents.
@mrcode Please open another question as this question is a new, different question.
@mrcode if my answer helped you, please consider upvoting it and, if it answers your question, feel free to mark as accepted :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.