ElasticSearch 6.x 父子文檔[join]分析

ES6.0之後,索引的type只能有一個,使得父子結構變的不那麼清晰,畢竟對於java開發者來講,index->db,type->table的結構比較容易理解。java

按照官方的說明,以前一個索引有多個type,若是有一個相同的字段在不一樣的type中出現,在ES底層實際上是按照一個field來作lucene索引的,這很具備迷惑性,容易形成誤解。因此6.0之後,全部的字段都在索引的_doc【默認type】中集中定義。假設索引中會有parent和child兩個類型的文檔,那麼可能parent引用了abcd字段,child引用了aef字段,各取所需。app

目前我用的es版本爲6.3,父子結構須要用join字段來定義,關係的映射用relations字段來指定。spa

一個索引中只能有一個join類型字段,若是定義一個以上的join字段,會報錯:Field [_parent_join] is defined twice in [_doc]
join字段中的relations集合,建好索引以後,能夠增長映射,或者給原有的映射添加child,可是不能刪除原有的映射。
好比,原有的relations定義爲:code

"myJoin": {
  "type": "join",
  "eager_global_ordinals": true,
  "relations": {
    "parent_a": child_a1
  }
}

如今經過updateMapping API增長一條映射parent_b,原有的映射增長了child_a2child_a3blog

"myJoin": {
  "type": "join",
  "eager_global_ordinals": true,
  "relations": {
    "parent_a": [
      "child_a1",
      "child_a2",
      "child_a3"
    ],
    "parent_b": "child_b"
  }
}

 中午睡了個午覺,接着再寫一點join的操做排序

  • 根據子文檔查詢父文檔
GET /test_index_join/_search
{
  "query": {
    "has_child": {
      "type": "child_a1",
      "score_mode": "max", 
      # 基於child_a1文檔定義來搜索,query裏的查詢字段是child_a1裏的
      "query": {
        "term": {
          "salesCount": 100
        }
      }
    }
  }
}
  • 根據子文檔對父文檔進行排序

說明:根據子文檔的字段影響父文檔的的得分,而後父文檔根據_score來排序。索引

下面例子中,父文檔的得分爲:_score * child_a1.salesCount,score_mode能夠是min,max,sum,avg,first等。ip

GET /test_index_join/_search
{
  "query": {
    "has_child": {
      "type": "child_a1",
      "score_mode": "max", 
      "query": {
        "function_score": {
          "script_score": {
            "script": "_score * doc['salesCount'].value"
          }
        }
      }
    }
  },
  "sort": [
    {
      "_score": {
        "order": "asc"
      }
    }
  ]
}

 還能夠依賴field_value_factor來影響父文檔得分,效果類似,效率更高;functions支持多個field影響因子,多個因子的默認[score_mode]計分模式爲multiply[相乘],還有其餘可選模式爲:min,max,avg,sum,first,multiply。開發

下面例子中,父文檔的得分爲:salesCount,由於沒有其餘的影響因子,若是有多個,則取最大的一個,由於score_mode爲max。文檔

GET /test_index_join/_search
{
  "query": {
    "has_child": {
      "type": "child_a1",
      "score_mode": "max", 
      "query": {
        "function_score": {
          "functions": [
            {
              "field_value_factor": {
                "field": "salesCount"
              }
            }
          ]
        }
      }
    }
  },
  "sort": [
    {
      "_score": {
        "order": "asc"
      }
    }
  ]
}

 

  • 根據父文檔查詢子文檔
GET /test_index_join/_search
{
  "query": {
    "has_parent": {
      "parent_type": "parnet_a",
      # 基於parnet_a來搜索,query裏的查詢字段是parnet_a裏的
      "query": {
        "range": {
          "price": {
            "gt": 1,
            "lte": 200
          }
        }
      }
    }
  }
}
相關文章
相關標籤/搜索