简体   繁体   中英

ElasticSearch NEST query across multiple types

Given the following POCOs:

public class Dog
{
    public string Name { get; set; }
}

public class Cat
{
    public string Name { get; set; }
    public bool Enabled { get; set; }
}

I would like to perform a query that returns ALL Dogs and only Cats that are Enabled.

The elastic docs provide the following example but not any detail on how to use a Bool with query or filter context to search for specific field values across multiple types:

.Search<object>(s => s
    .Size(100)
    .Type(Types.Type(typeof(Dog), typeof(Cat)))                
    .Query(...)

How do I perform my query?, Thanks in advance

We can query on the metadata _type field and combine this with queries on other fields. Here's an example. We'll create 100 cats and 100 dogs, setting each even cat to be disabled

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "pets";
    var connectionSettings = new ConnectionSettings(pool)
            .DefaultIndex(defaultIndex);

    var client = new ElasticClient(connectionSettings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    client.CreateIndex(defaultIndex, ci => ci
        .Mappings(m => m
            .Map<Dog>(d => d.AutoMap())
            .Map<Cat>(c => c.AutoMap())
        )
    );

    var dogs = Enumerable.Range(1, 100).Select(i => new Dog
    {
        Name = $"Dog {i}"
    });

    client.IndexMany(dogs);

    var cats = Enumerable.Range(1, 100).Select(i => new Cat
    {
        Name = $"Cat {i}",
        Enabled = i % 2 == 0 ? false : true
    });

    client.IndexMany(cats);
    client.Refresh(defaultIndex);

    client.Search<object>(s => s
        .Size(100)
        .SearchType(SearchType.Count)
        .Type(Types.Type(typeof(Dog), typeof(Cat)))
        .Query(q => 
            (+q.Term("_type", "cat") && +q.Term("enabled", true)) ||
            +q.Term("_type", "dog")
        )
    );
}

The search query takes advantage of operator overloading; the unary + operator will mean that the query will be wrapped in a bool query filter and similarly, && will wrap into a bool query must (or filter in this case as we also use the + unary operator to make it a filter), and || will wrap into a bool query should . The resulting executed query looks like

{
  "size": 100,
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "filter": [
              {
                "term": {
                  "_type": {
                    "value": "cat"
                  }
                }
              },
              {
                "term": {
                  "enabled": {
                    "value": true
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "filter": [
              {
                "term": {
                  "_type": {
                    "value": "dog"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

which yields

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 150,
    "max_score" : 0.0,
    "hits" : [ ]
  }
}

This is only a count, but if you were to look at the documents, it would be all dogs and only cats that are enabled

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM