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


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

按照官方的說明,之前一個索引有多個type,如果有一個相同的字段在不同的type中出現,在ES底層其實是按照一個field來做lucene索引的,這很具有迷惑性,容易造成誤解。所以6.0以后,所有的字段都在索引的_doc【默認type】中集中定義。假設索引中會有parent和child兩個類型的文檔,那么可能parent引用了abcd字段,child引用了aef字段,各取所需。

目前我用的es版本為6.3,父子結構需要用join字段來定義,關系的映射用relations字段來指定。

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

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

現在通過updateMapping API增加一條映射parent_b,原有的映射增加了child_a2child_a3

"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等。

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
          }
        }
      }
    }
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM