web-dev-qa-db-ja.com

複数の用語を含むNEST条件付きフィルタークエリ

このようなElasticSearchクエリを実行したいと思います。

{
    "query" :
    {
        "bool" :
        {
            "filter" : [
                {
                    "terms" :
                    {
                        "name" : ["name1", "name2"]
                    }
                },
                {
                    "terms" :
                    {
                        "color" : ["orange", "red"]
                    }
                }
            ]
        }
    }
}

私はこのようにNESTでそれを実装しようとしました:

_elasticClient
    .SearchAsync<MyDocument>(s =>
        s.Index("myindex")
            .Query(q => q
                .Bool(bq => bq
                    .Filter(fq =>
                    {
                        QueryContainer query = null;

                        if (nameList.Any()) {
                            query &= fq.Terms(t => t.Field(f => f.Name).Terms(nameList));
                        }

                        if (colorList.Any()) {
                            query &= fq.Terms(t => t.Field(f => f.Color).Terms(colorList));
                        }

                        return query;
                    })
                )
            )
    );

しかし、それによって、フィルターがbool must内にラップされている次のようなクエリが得られます。

{
    "query" :
    {
        "bool" :
        {
            "filter" : [
                {
                    "bool" :
                    {
                        "must" : [
                            {
                                "terms" :
                                {
                                    "name" : ["name1", "name2"]
                                }
                            },
                            {
                                "terms" :
                                {
                                    "color" : ["orange", "red"]
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

NESTコードを変更して正しいクエリを取得するにはどうすればよいですか?私の用語をQueryContainer以外のものに追加する必要がありますか?

16
dhrm

以下に示すように条件付きフィルターをチェックする場合は、クエリを実行する前にフィルターのリストを作成できます。

var nameList = new[] {"a", "b"};
var colorList = new[] {1, 2};

var filters = new List<Func<QueryContainerDescriptor<MyDocument>, QueryContainer>>();
if (nameList.Any())
{
     filters.Add(fq=> fq.Terms(t => t.Field(f => f.Name).Terms(nameList)));
}

if (colorList.Any())
{
    filters.Add(fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList)));
}

ISearchResponse<Property> searchResponse =
     elasticClient.Search<MyDocument>(x => x.Query(q => q
     .Bool(bq => bq.Filter(filters))));

フィルタークエリを作成する前に条件を確認する必要がない場合は、次のようにすることができます。

ISearchResponse<MyDocument> searchResponse =
elasticClient.Search<MyDocument>(x => x.Query(q => q
.Bool(bq => bq
.Filter(
        fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
        fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
        ))));
25
Adam Łepkowski

BoolクエリのFilterメソッドは_params Func<QueryContainerDescriptor<T>, QueryContainer>[]_を取るため、複数の式を渡して複数のフィルターを表すことができます

_var nameList = new string[] { "name1", "name2" };
var colorList = new string[] { "orange", "red" };

client.SearchAsync<MyDocument>(s => s
        .Index("myindex")
        .Query(q => q
            .Bool(bq => bq
                .Filter(
                    fq => fq.Terms(t => t.Field(f => f.Name).Terms(nameList)),
                    fq => fq.Terms(t => t.Field(f => f.Color).Terms(colorList))
                )
            )
        )
);
_

その結果

_{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "name": [
              "name1",
              "name2"
            ]
          }
        },
        {
          "terms": {
            "color": [
              "orange",
              "red"
            ]
          }
        }
      ]
    }
  }
}
_

NESTには無条件クエリの概念もあります 、つまり、クエリが無条件であると判断された場合、ではありませんリクエストの一部としてシリアル化されます。

無条件とはどういう意味ですか?それはクエリによって異なります。たとえば、termsクエリの場合、次のいずれかに該当する場合は無条件と見なされます。

  • fieldに値がありません
  • 用語値リストはnullです
  • 条件値は空のコレクションです
  • 用語値リストには値がありますが、すべてnullまたは空の文字列です

実証する

_var emptyNames = new string[] {};
string[] nullColors = null;

client.SearchAsync<MyDocument>(s =>
s.Index("myindex")
    .Query(q => q
        .Bool(bq => bq
            .Filter(
                fq => fq.Terms(t => t.Field(f => f.Name).Terms(emptyNames)),
                fq => fq.Terms(t => t.Field(f => f.Color).Terms(nullColors)))
        )
    )
);
_

結果は

_{}
_

条件なしクエリは、クエリを作成する前にコレクションに値があるかどうかを確認する必要がないという点で、NESTクエリの作成を容易にするのに役立ちます。クエリごとに無条件のセマンティクスを変更できます .Strict()および.Verbatim() を使用します。

12
Russ Cam
var searchResponse = client.Search<EventData>(s => s
            .From(0)
            .Query(q => q
                    .Bool(bq => bq
                    .Filter(
                            fq => fq.Terms(t => t.Field(f => f.Client.Id).Terms(17)),
                            fq => fq.Terms(t => t.Field(f => f.Item.Id).Terms(**new[] { 34983, 35430, 35339, 35300 }**)), 
                            fq => fq.Terms(t=>t.Field(f=>f.Event).Terms("Control de Panico")),
                            fq => fq.DateRange(dr => dr.Field(f => f.DateTime)
                                .GreaterThanOrEquals(new DateTime(2018, 07, 01))
                                .LessThanOrEquals(new DateTime(2018, 10, 02)))
                            )
                  ))
            .Size(2000)
            .Sort(g => sortDescriptor)
            );
0
Sharon AS