orderBy -> sort

orderBy句は、ElasticSearch のsort に変換されます。

firstRows/maxRows -> from/size

firstRowsmaxRowsは、それぞれElasticSearch のfrom と size に変換されます。

select/fetch -> fields/include

ORMクエリのselect句とfetch句は、ElasticSearch のfields_source include に変換されます。参考として、検索時の Elasticsearch フィールドの管理があります。

Ebean は、fetch が「パスに対するすべてのプロパティを取得する」*である場合、またはパスがOneToManyまたはManyToManyの場合、fetch()句を_source includeに変換します。

特定のクエリを最適化したい(オートコンプリートUIなどをサポートするため)ケースがあり、それらのクエリに対して取得したいフィールドを保存することで(ElasticSearchが_sourceから読み取る必要がなくなる)、fields を使用してそれらのフィールドのみを取得できます。これは、「顧客名」や「製品名」などのオートコンプリートをサポートする場合に、idとnameフィールドのみが必要になるようなユースケースを想定しています。

select()またはfetch()が指定されていない場合、クエリにはfieldsセクションまたは_sourceセクションが含まれず、ElasticSearchは_sourceを返します。

where -> filter context

whereに追加された式は、ElasticSearch のfilter context の式になります。

filter context の式はスコアリングされず、関連性の順序付けには参加しません。filter context の式の利点は、ElasticSearch によってキャッシュされてパフォーマンスが向上することです。

デフォルトでは、where() 式はMUSTで結合されます。

複数の式がwhere()に追加されると、デフォルトでMUSTを使用して追加され、これはANDという「オブジェクトリレーショナル」のデフォルトと一貫しています。

例:filter context

PagedList<Order> orders =
  Order.find
    .where()
      // default to MUST for where()
      .customer.name.istartsWith("Rob")
      .status.eq(Order.Status.COMPLETE)
    .setMaxRows(50)
    .setUseDocStore(true)
    .findPagedList();
{
  "size": 50,
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            { "prefix": { "customer.name": "rob" } },
            { "term": { "status": "COMPLETE" } }
          ]
        }
      }
    }
  }
}

text -> query context

textに追加された式は、ElasticSearch のquery context の式になります。これらの式はスコアリングされ、ドキュメントの関連性の順序付けに使用されます。

式がtext()に追加されると、クエリは自動的にドキュメントストアクエリとみなされます。

デフォルトでは、text() 式はSHOULDで結合されます。

複数の式がtext()に追加されると、デフォルトでSHOULDを使用して追加され、これはORという「オブジェクトリレーショナル」のデフォルトと一貫しています。

例:query context

PagedList<Order> orders =
  Order.find
    .text()
      // implicitly sets setUseDocStore(true)
      // goes to ElasticSearch 'query context'
      // defaults to SHOULD for text()
      .customer.name.match("Rob")
      .status.eq(Order.Status.COMPLETE)
    .setMaxRows(50)
    .findPagedList();
{
  "size": 50,
  "query": {
    "bool": {
      "should": [
        { "match": { "customer.name": "Rob" } },
        { "term": { "status": "COMPLETE" } }
      ]
    }
  }
}

例:query context と filter context

「全文検索」クエリには、以下の例のようにquery contextfilter contextの両方が含まれる場合があります。

List<Order> orders = Order.find
    .text() // 'query context'
      .must()
        .customer.name.match("Rob")
        .customer.name.match("Bygr")
        .endJunction()
      .mustNot()
        .customer.status.eq(Customer.Status.ACTIVE)
    .where() // 'filter context'
      .should()
        .status.eq(Order.Status.COMPLETE)
        .status.isNotNull()
    .findList();
{
  "query": {
    "bool": {
      "must": [
        { "match": { "customer.name": "Rob" } },
        { "match": { "customer.name": "Bygr" } }
      ],
      "must_not": [
        { "term": { "customer.status": "ACTIVE" } }
      ]
    }
  },
  "filter": {
    "bool": {
      "should": [
        { "term": { "status": "COMPLETE" } },
        { "exists": { "field": "status" } }
      ]
    }
  }
}

明示的な useDocStore(true)

useDocStore(true)が設定されている場合、クエリはElasticSearchに対して実行されます。

暗黙的な useDocStore(true)

クエリは、次の場合に暗黙的にドキュメントストアクエリとして設定されます。

  • text()が使用される場合
  • テキスト接合が使用される場合 - must()mustNot()should()
  • 「全文検索」式が使用される場合 - match()multiMatch()textSimple()textQueryString()textCommonTerms()

Must、must not、should

MUSTMUST NOTSHOULDは、テキスト検索で使用される接合式であり、それぞれANDNOTORにマッピングされます。

通常のORMクエリではmust()mustNot()should()を使用できません。これらの「テキスト検索接合式」のいずれかを使用すると、クエリは自動的にドキュメントストアクエリと見なされ、ElasticSearchにヒットします。

Product
 .where()
   // we used must() so automatically
   // becomes a doc store query
   .must()
     .sku.equalTo("C002")
     .findList();

式を結合するには、must()mustNot()should()を使用します。

List<Customer> customers =
  server.find(Customer.class)
    .text()
    .must()
      .match("name", "Rob")
      .match("smallNote", "interesting")
    .findList();
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "Rob" } },
        { "match": { "smallNote": "interesting" } }
      ]
    }
  }
}

別の接合を開始するために、「現在の接合」を終了するにはendJunction()を使用します。

List<Order> orders = Order.find
    .text() // 'query context'
      .must()
        .customer.name.match("Rob")
        .customer.name.match("Bygr")
        .endJunction()
      .mustNot()
        .customer.status.eq(Customer.Status.ACTIVE)
    .where() // 'filter context'
      .should()
        .status.eq(Order.Status.COMPLETE)
        .status.isNotNull()
    .findList();
{
  "query": {
    "bool": {
      "must": [
        { "match": { "customer.name": "Rob" } },
        { "match": { "customer.name": "Bygr" } }
      ],
      "must_not": [
        { "term": { "customer.status": "ACTIVE" } }
      ]
    }
  },
  "filter": {
    "bool": {
      "should": [
        { "term": { "status": "COMPLETE" } },
        { "exists": { "field": "status" } }
      ]
    }
  }
}

Match

MatchはElasticSearch専用の式であり、使用されるとクエリは自動的にドキュメントストアクエリとして扱われます。

クエリビーンの場合、match()式は文字列型のプロパティで使用できます。

List<Order> orders =
  new QOrder()
    .customer.name.match("Rob")
    .findList();
{
  "query": {
    "match": {
      "customer.name": "Rob"
    }
  }
}

Multi match、Text simpleなど

multiMatch()textSimple()textCommonTerms()textQueryString()はすべてElasticSearch専用の式であり、これらを使用するとクエリは自動的にドキュメントストアクエリになります。

これらの式は、複数のフィールドまたはドキュメント全体(_all フィールド)に適用される「クエリレベル」の式です。

MultiMatch multiMatch =
  MultiMatch.fields("customer.name", "customer.notes")
    .opAnd()
    .type(MultiMatch.Type.PHRASE_PREFIX);

new QOrder()
    .multiMatch("Rob", multiMatch)
    .findList();
{"query": {
  "multi_match": {
    "query": "Rob",
    "fields": [
      "customer.name",
      "customer.notes"
    ],
    "type": "phrase_prefix",
    "operator": "and"
  }
}}

テキスト式

match

matchはElasticSearch のmatch クエリ にマッピングされます。

multi match

multi matchはElasticSearch のmulti match クエリ にマッピングされます。

text simple

text simpleはElasticSearch のsimple query string クエリ にマッピングされます。

text query string

text query stringはElasticSearch のquery string クエリ にマッピングされます。

text common terms

text common termsはElasticSearch のcommon terms クエリ にマッピングされます。