天天看點

ElasticSearch 7.6 多子文檔過濾查詢一、es 7.x 父子文檔的 field 及官方文檔位址二、父子文檔結構設計三、request query

一、es 7.x 父子文檔的 field 及官方文檔位址

我找了半天,原來官方本來就有教程,隻不過專有名詞沒用對,是以在找官方文檔的時候,一直徘徊不前,不說了,先去弄寫代碼了。後面有時間了在繼續寫。

es 關鍵字詳解

es 7.x 支援的 field。

es 7.x 父子文檔 Join,

es 7.x search request API

es 7.6 Java High Level REST Client API

es 各種 Client

以下例子皆是以 es 7.6.0 基礎上進行的,docker 安裝友善快捷。記得安裝 kibana

二、父子文檔結構設計

  1. 這裡需要注意一下,就是對于一些特定的屬性最好在建立文檔的時候就進行定義,比如 date 類型,可以接收什麼類型的,boolean、數組、對象等。
    ElasticSearch 7.6 多子文檔過濾查詢一、es 7.x 父子文檔的 field 及官方文檔位址二、父子文檔結構設計三、request query

1. 總結構

PUT kikuu_test_product

{
    "settings": {
        "number_of_shards": 2,
        "number_of_replicas": 0,
        "refresh_interval": "50s"
    },
    "mappings": {
        "properties": {
            "productType": { 
            "type": "join",
                "relations": {
                    "product": [
                    "promotionActivityProduct",
                    "store"
                    ]
                }
            },
            "productStatus": {
                "type": "integer"
            },
            "productName": {
                "type": "keyword"
            },
           "productPrice": {
                "type": "keyword"
            },
           "productLowestPrice": {
                "type": "double"
            },
            "storeId": {
                "type": "keyword"
            },
            "storeStatus":{
                "type":"integer"
            },
            "startDate":{
                "type": "date",
                "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
            },
            "endDate":{
                "type": "date",
                "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
            }
        }
    }
}

//如果後面還想再加資料的 field
PUT kikuu_test_product/_mapping
{
  "properties":{
    "startDate":{
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
    },
    "endDate":{
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
    }
  }
}
           

2. 插入測試資料

如果在原來結構的基礎上在添加新的 field,那麼 es 會自動識别,極有可能識别出來的 field 的類型是 keyword
是以在設計 es 資料結構的時候,最好把重要的一些結構進行定義,以防止後面 es 自動識别成 keyword

① 父文檔資料

以下是測試資料 ,request Rest

PUT kikuu_test_product/_doc/1?refresh
{
    "productType": {
        "name":"product"
    },
    "productName":"skirt",
    "productPrice":"221.005",
    "storeNumber":14384,
    "storeId":1,
    "productStatus":3
}
           

執行該請求 100 次 每次需要改一些内容,我是直接使用資料庫裡面的資料取表後在網站執行 excel 轉 json 後用代碼執行的。

如果懶的找我提供一下。

需要提前配置 High Level Rest Client

@Data
@Document(indexName = "kikuu_test_product", shards=2, refreshInterval="-1")
public static class ESProduct {
    String id;
    Integer productStatus;
    String productName;
    BigDecimal productPrice;
    Long storeId;
    ProductType productType = new ProductType();

	public static class ProductType {
        String name = "product";
    }
}
    
	public static String getProductJsonString() {
        return  "{\"list\":[{\"id\":\"17\",\"productStatus\":\"3\",\"productName\":\"14K Necklace Inlayed Stone (03107A-01)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"19\",\"productStatus\":\"3\",\"productName\":\"14K Necklace Inlayed Stone (03108A-01)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"20\",\"productStatus\":\"3\",\"productName\":\"14K Necklace Inlayed Stone (03109A-01)\",\"productPrice\":\"8\",\"storeId\":\"1\"},{\"id\":\"21\",\"productStatus\":\"3\",\"productName\":\"14K Necklace Inlayed Stone (03110A-01)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"22\",\"productStatus\":\"3\",\"productName\":\"14K Necklace Inlayed Stone (03111A-01)\",\"productPrice\":\"8\",\"storeId\":\"1\"},{\"id\":\"23\",\"productStatus\":\"3\",\"productName\":\"14K bracelet (04122A-01)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"24\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07123A)\",\"productPrice\":\"13\",\"storeId\":\"1\"},{\"id\":\"25\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07124A)\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"26\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07125A)\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"27\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07126A)\",\"productPrice\":\"9\",\"storeId\":\"1\"},{\"id\":\"28\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07127A)\",\"productPrice\":\"12\",\"storeId\":\"1\"},{\"id\":\"29\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07128A)\",\"productPrice\":\"13\",\"storeId\":\"1\"},{\"id\":\"30\",\"productStatus\":\"3\",\"productName\":\"4 shoolbag\",\"productPrice\":\"9\",\"storeId\":\"1\"},{\"id\":\"31\",\"productStatus\":\"3\",\"productName\":\"14K Suit Inlayed Stone (07130A)\",\"productPrice\":\"11\",\"storeId\":\"1\"},{\"id\":\"32\",\"productStatus\":\"3\",\"productName\":\"18K Bracelet Inlayed Stone (04131A-02)\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"33\",\"productStatus\":\"3\",\"productName\":\"4 skirt\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"34\",\"productStatus\":\"3\",\"productName\":\"18K Bracelet Inlayed Stone (04133A-02)\",\"productPrice\":\"11\",\"storeId\":\"1\"},{\"id\":\"35\",\"productStatus\":\"3\",\"productName\":\"18K Bracelet Inlayed Stone (04134A-02)\",\"productPrice\":\"7\",\"storeId\":\"1\"},{\"id\":\"36\",\"productStatus\":\"3\",\"productName\":\"14K Bracelet Inlayed Stone (04135A-01)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"37\",\"productStatus\":\"3\",\"productName\":\"18K Bracelet Inlayed Stone (04136A-02)\",\"productPrice\":\"26\",\"storeId\":\"1\"},{\"id\":\"38\",\"productStatus\":\"3\",\"productName\":\"18K Two Bracelets (04137A-02)\",\"productPrice\":\"11\",\"storeId\":\"1\"},{\"id\":\"39\",\"productStatus\":\"3\",\"productName\":\"18K Bracelet Inlayed Stone (04138A-02)\",\"productPrice\":\"15\",\"storeId\":\"1\"},{\"id\":\"40\",\"productStatus\":\"3\",\"productName\":\"uuu\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"41\",\"productStatus\":\"3\",\"productName\":\"14K Bracelet Inlayed Stone (04141A-01)\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"42\",\"productStatus\":\"3\",\"productName\":\"14K Bracelet Inlayed Stone (04142A-01)\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"43\",\"productStatus\":\"3\",\"productName\":\"14K Bracelet Inlayed Stone (04143A-01)\",\"productPrice\":\"15\",\"storeId\":\"1\"},{\"id\":\"44\",\"productStatus\":\"3\",\"productName\":\"uuu\",\"productPrice\":\"16\",\"storeId\":\"1\"},{\"id\":\"45\",\"productStatus\":\"3\",\"productName\":\"14K Bracelet Inlayed Stone (04145A-01)\",\"productPrice\":\"14\",\"storeId\":\"1\"},{\"id\":\"46\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07146A)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"47\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07147A)\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"48\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07148A)\",\"productPrice\":\"7\",\"storeId\":\"1\"},{\"id\":\"49\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07149A)\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"50\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07150A)\",\"productPrice\":\"12\",\"storeId\":\"1\"},{\"id\":\"51\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07151A)\",\"productPrice\":\"13\",\"storeId\":\"1\"},{\"id\":\"52\",\"productStatus\":\"3\",\"productName\":\"18K Suit Inlayed Stone (07152A)\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"54\",\"productStatus\":\"0\",\"productName\":\"123 shirt\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"60\",\"productStatus\":\"3\",\"productName\":\"18K Gold Plated Necklace Fashion Street\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"61\",\"productStatus\":\"3\",\"productName\":\"18K Gold Plated Necklace Fashion Street (03007A-05)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"62\",\"productStatus\":\"3\",\"productName\":\"18K Gold Plated Fashion Court Necklace\",\"productPrice\":\"7\",\"storeId\":\"1\"},{\"id\":\"63\",\"productStatus\":\"3\",\"productName\":\"18K Street Fashion Necklace(03013A-05)\",\"productPrice\":\"4\",\"storeId\":\"1\"},{\"id\":\"64\",\"productStatus\":\"3\",\"productName\":\"18K Gold Plated Necklace (03017A-05)\",\"productPrice\":\"4\",\"storeId\":\"1\"},{\"id\":\"67\",\"productStatus\":\"3\",\"productName\":\"18 K Gold-Plated Palace Style Necklace (07004A-05)\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"69\",\"productStatus\":\"3\",\"productName\":\"18 K Gold Plated Women's Bracelet (05001A-05)\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"70\",\"productStatus\":\"3\",\"productName\":\"18 K Gold Plated Women's Bracelet (05003A-05)\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"71\",\"productStatus\":\"3\",\"productName\":\"18 K Gold Plated Scripture Bracelet (05005A-05)\",\"productPrice\":\"9\",\"storeId\":\"1\"},{\"id\":\"73\",\"productStatus\":\"3\",\"productName\":\"18 K Gold Plated women's Bracelet (05007A-05)\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"74\",\"productStatus\":\"3\",\"productName\":\"18 K Gold Plated Bracelet (05008A-05)\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"85\",\"productStatus\":\"20\",\"productName\":\"TEST01\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"86\",\"productStatus\":\"20\",\"productName\":\"Retro flowers mother-of-pearl Mosaic gold bracelet \",\"productPrice\":\"7\",\"storeId\":\"1\"},{\"id\":\"87\",\"productStatus\":\"20\",\"productName\":\"Product IMG Test\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"88\",\"productStatus\":\"20\",\"productName\":\"Retro flower hollow out pattern jewelry set\",\"productPrice\":\"11\",\"storeId\":\"1\"},{\"id\":\"89\",\"productStatus\":\"3\",\"productName\":\"Zircon allergy free small dolphin pendant\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"90\",\"productStatus\":\"20\",\"productName\":\"Palace restoring ancient ways suit flowers\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"91\",\"productStatus\":\"3\",\"productName\":\"Color zircon bracelets\",\"productPrice\":\"9\",\"storeId\":\"1\"},{\"id\":\"92\",\"productStatus\":\"3\",\"productName\":\"Auspicious phoenix bangles\",\"productPrice\":\"5\",\"storeId\":\"1\"},{\"id\":\"93\",\"productStatus\":\"3\",\"productName\":\"Lily Chinese style bracelet\",\"productPrice\":\"6\",\"storeId\":\"1\"},{\"id\":\"94\",\"productStatus\":\"3\",\"productName\":\"Gold-plated fashion twisted rope long necklace\",\"productPrice\":\"7\",\"storeId\":\"1\"},{\"id\":\"95\",\"productStatus\":\"20\",\"productName\":\"Elegant color restoring ancient ways earrings\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"96\",\"productStatus\":\"3\",\"productName\":\"圖檔轉移\",\"productPrice\":\"20\",\"storeId\":\"1\"},{\"id\":\"97\",\"productStatus\":\"3\",\"productName\":\"TEST Product\",\"productPrice\":\"10\",\"storeId\":\"1\"},{\"id\":\"98\",\"productStatus\":\"3\",\"productName\":\"TEST Product\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"99\",\"productStatus\":\"20\",\"productName\":\"TEST Product\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"100\",\"productStatus\":\"3\",\"productName\":\"好東西\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"101\",\"productStatus\":\"20\",\"productName\":\"TEST-Product-1\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"102\",\"productStatus\":\"3\",\"productName\":\"Sexy have administrative levels feeling of the ear ring\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"107\",\"productStatus\":\"20\",\"productName\":\"Grimace Gauze Mask\",\"productPrice\":\"3\",\"storeId\":\"3\"},{\"id\":\"108\",\"productStatus\":\"20\",\"productName\":\"Hollow Beads Earrings\",\"productPrice\":\"4\",\"storeId\":\"3\"},{\"id\":\"109\",\"productStatus\":\"20\",\"productName\":\"Pirate Hollow Earrings\",\"productPrice\":\"3\",\"storeId\":\"3\"},{\"id\":\"110\",\"productStatus\":\"20\",\"productName\":\"Hollow Party Mask\",\"productPrice\":\"3\",\"storeId\":\"3\"},{\"id\":\"111\",\"productStatus\":\"3\",\"productName\":\"Flower Hollow Bracelet\",\"productPrice\":\"4\",\"storeId\":\"3\"},{\"id\":\"112\",\"productStatus\":\"3\",\"productName\":\"Pumpkin Hollow Brooch\",\"productPrice\":\"5\",\"storeId\":\"3\"},{\"id\":\"113\",\"productStatus\":\"20\",\"productName\":\"Halloween Lip and Wolf Fang Earrings\",\"productPrice\":\"4\",\"storeId\":\"3\"},{\"id\":\"114\",\"productStatus\":\"20\",\"productName\":\" Solid Color 3D Clutch Bag(PU Synthetic Leather)\",\"productPrice\":\"6\",\"storeId\":\"3\"},{\"id\":\"115\",\"productStatus\":\"20\",\"productName\":\"Cable Chain Bat Pendant Earrings\",\"productPrice\":\"3\",\"storeId\":\"3\"},{\"id\":\"116\",\"productStatus\":\"20\",\"productName\":\"Halloween Color Block Eye Pattern Clutch Bag\",\"productPrice\":\"7\",\"storeId\":\"3\"},{\"id\":\"118\",\"productStatus\":\"3\",\"productName\":\"Halloween Heart Shape Diamante Necklace\",\"productPrice\":\"7\",\"storeId\":\"3\"},{\"id\":\"119\",\"productStatus\":\"20\",\"productName\":\"Halloween Clock Print Wallet\",\"productPrice\":\"8\",\"storeId\":\"3\"},{\"id\":\"121\",\"productStatus\":\"20\",\"productName\":\"Geometric Shoulder Bag(PU Synthetic Leather)\",\"productPrice\":\"40\",\"storeId\":\"3\"},{\"id\":\"123\",\"productStatus\":\"3\",\"productName\":\"Cross-body HandBag\",\"productPrice\":\"37\",\"storeId\":\"3\"},{\"id\":\"124\",\"productStatus\":\"20\",\"productName\":\"Pure Color Shoulder Bag for Women(PVC Faux Leather)\",\"productPrice\":\"40\",\"storeId\":\"3\"},{\"id\":\"127\",\"productStatus\":\"3\",\"productName\":\"CHIC Four sets Tassel Shoulder Bag(PVC Faux Leather)\",\"productPrice\":\"10.6\",\"storeId\":\"3\"},{\"id\":\"132\",\"productStatus\":\"20\",\"productName\":\"Dotted Cutout Dress\",\"productPrice\":\"27\",\"storeId\":\"3\"},{\"id\":\"134\",\"productStatus\":\"20\",\"productName\":\"Print Beaded Hat\",\"productPrice\":\"12\",\"storeId\":\"3\"},{\"id\":\"136\",\"productStatus\":\"3\",\"productName\":\"Skull Geometric Necklace\",\"productPrice\":\"4\",\"storeId\":\"3\"},{\"id\":\"137\",\"productStatus\":\"3\",\"productName\":\"Cloud and Tower Necklace\",\"productPrice\":\"7\",\"storeId\":\"3\"},{\"id\":\"138\",\"productStatus\":\"3\",\"productName\":\"Fireworks gold-plated lovely earrings\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"139\",\"productStatus\":\"3\",\"productName\":\"Hollow Skull Necklace\",\"productPrice\":\"4\",\"storeId\":\"3\"},{\"id\":\"141\",\"productStatus\":\"20\",\"productName\":\"Three-dimensional Floral Sequined Dress\",\"productPrice\":\"27\",\"storeId\":\"3\"},{\"id\":\"142\",\"productStatus\":\"20\",\"productName\":\"Crisscross Backless Dress\",\"productPrice\":\"22\",\"storeId\":\"3\"},{\"id\":\"144\",\"productStatus\":\"20\",\"productName\":\"Backless Strappy Dress\",\"productPrice\":\"24\",\"storeId\":\"3\"},{\"id\":\"145\",\"productStatus\":\"20\",\"productName\":\"Vintage Zipper Dress\",\"productPrice\":\"25\",\"storeId\":\"3\"},{\"id\":\"153\",\"productStatus\":\"3\",\"productName\":\"Purple crystal pendant\",\"productPrice\":\"26\",\"storeId\":\"4\"},{\"id\":\"170\",\"productStatus\":\"20\",\"productName\":\"Bebear Baby Carrier 3 in 1 Carry Ways Front Carry\",\"productPrice\":\"16\",\"storeId\":\"2\"},{\"id\":\"171\",\"productStatus\":\"3\",\"productName\":\"Vintage Chic earrings\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"172\",\"productStatus\":\"3\",\"productName\":\"Fashion square earrings\",\"productPrice\":\"3\",\"storeId\":\"1\"},{\"id\":\"173\",\"productStatus\":\"3\",\"productName\":\"Eyes sparkling stud earrings\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"174\",\"productStatus\":\"20\",\"productName\":\"Bebear Baby Backpack Carrier with Foldable Head Cover\",\"productPrice\":\"23\",\"storeId\":\"2\"},{\"id\":\"175\",\"productStatus\":\"3\",\"productName\":\"Lucky clover earrings\",\"productPrice\":\"2\",\"storeId\":\"1\"},{\"id\":\"176\",\"productStatus\":\"20\",\"productName\":\"Bebear Ergonomic Baby Carrier Baby Sling\",\"productPrice\":\"25\",\"storeId\":\"2\"},{\"id\":\"177\",\"productStatus\":\"20\",\"productName\":\"Bebear Baby Wrap Carrier with Small Pockets\",\"productPrice\":\"18\",\"storeId\":\"2\"}]}";
    }


    public List<ESProduct> getProductList() {
        List<ESProduct> list = new ArrayList<>();
        JsonObject jsonObject = new JsonParser().parse(getProductJsonString()).getAsJsonObject();
        JsonElement elements = jsonObject.get("list");
        JsonArray asJsonArray = elements.getAsJsonArray();
        for (int i = 0; i < asJsonArray.size(); i++) {
            String json = asJsonArray.get(i).toString();
            list.add(new Gson().fromJson(json, ESProduct.class));
        }
        return list;
    }

    public static final String TEST_PRODUCT = "kikuu_test_product";
    @Test
    void addDocument() throws IOException {
        IndexRequest request = new IndexRequest(TEST_PRODUCT);
        List<ESProduct> productList = getProductList();
        for (ESProduct each : productList) {
            request.id(each.getId());
            request.source(new Gson().toJson(each), XContentType.JSON);
            elasticsearchClient.index(request, RequestOptions.DEFAULT);
        }
    }
           

② promotionActivityProduct 資料

這個就不給資料了,這個是我自己改的資料。

  1. 平均 5-6 個左右就行了,最好和下面的有交叉 (就是父文檔指向的是同一個)
  2. routing 和 parent 需要指向同一個父文檔的 id
  3. 一個商品對應一個活動商品
PUT /kikuu_test_product/_doc/a1?routing=22&refresh
{
    "productType": {
        "name":"promotionActivityProduct",
        "parent":"22"
    },
	"activityId": "1212420",
	"startDate": "2021-06-04 00:00:00",
	"endDate": "2021-06-30 00:00:00",
	"ActivityName": "Hot sale"
}
           

③ 插入子文檔 store 資料

  1. 一個商品對應一個店鋪
  2. 平均 5-6 個左右就行了,最好和上面的有交叉
  3. storeStatus 狀态 == 20 時店鋪是正常營業狀态。
PUT /kikuu_test_product/_doc/s6?routing=19&refresh
{
    "productType": {
        "name":"store",
        "parent":"19"
    },
    "storeId":"4",
    "storeStatus":20,
    "storeName":"Bebamour"
}
           

三、request query

官網 API Elasticsearch Reference

// 查詢所有文檔的productType 為 promotionActivityProduct
GET /kikuu_test_product/_search
{
  "query": {
    //"bool":{
      //"must":{
        "match": {
          //"productType":"product"
          "productType":"promotionActivityProduct"
          //"productType":"store"
        }
      }//,
      //"filter": [
      //  {"range": {"startDate": {"gte":"2021-01-01"}}}
      //]
    //}
  //}
}

// search 按父文檔 id 查子文檔
GET /kikuu_test_product/_search
{
    "query": {
    "parent_id": { 
      "type": "promotionActivityProduct",
      "id": "19"
    }
  }
}

// 查詢所有子文檔是 [活動/店鋪] 的父文檔
GET /kikuu_test_product/_search
{
    "query": {
    "has_child": { 
      "type": "promotionActivityProduct",
      //"type": "store",
      "query" : {
          "match_all" : {}
        }
    }
  }
}

// 查詢子文檔比對條件的父文檔
GET /kikuu_test_product/_search
{
  "query": {
    "has_child": {
      "type": "promotionActivityProduct",
      "query": {
        //"match_all" : {}
        "bool":{
          "must":{
            "match": {
              "activityId": "1212420"
            }
          }
        }
      }
    }
  }
}

// 查詢父文檔 根據 子文檔滿足的條件過濾
GET /kikuu_test_product/_search
{
  "query": {
    "has_child": {
      "type": "promotionActivityProduct",
      //"type":"store",
      "query": {
        "bool": {
          "filter": [
            {"range": {"startDate": {"gte":"2021-01-01"}}},
            {"range":{"endDate":{"lte":"2022-01-31"}}}
            //{"term":{"storeStatus":20}}
          ]
        }
      }
    }
  }
}

// 多子文檔按條件過濾
GET /kikuu_test_product/_search
{
  "query": {
    "bool": {
      "filter": [
        {"has_child": {
            "type": "promotionActivityProduct",
            "query": {
              "bool": {
                "filter": [
                  {"range": {"startDate": {"gte": "2021-01-01"}}},
                  {"range": {"endDate": {"lte": "2021-01-31"}}}
                ]
              }
            }
            ,"inner_hits": {}  // 顯示對應的子文檔
          }
        }
        ,{"has_child":{
            "type":"store",
            "query":{
              "bool":{
                "filter":[
                  {"term":{"storeStatus":20}}
                ]
              }
            }
            ,"inner_hits": {} // 顯示對應的子文檔
          }
        }
        //,{"range":{"productPrice":{"gte":5}}}
      ]
    }
  }
}
           

1. SpringBoot Java High Level REST

  1. 以 7.6 版本 為例 High Level REST Client API

① SpringBoot 配置

  1. pom.xml
<!-- 指定引用 es jar 的版本 ,版本一定要比對-->
    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.6.0</elasticsearch.version>
    </properties>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        
        <!-- gson  -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>
           
  1. application.properties
# es config
elasticsearch.clustername=docker-cluster
elasticsearch.address=192.168.10.143
elasticsearch.port=9201
           
  1. config client
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    @Value("${elasticsearch.clustername}")
    private String clusterName;

    @Value("${elasticsearch.address}")
    private String searchAddress;

    @Value("${elasticsearch.port}")
    private String port;

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(searchAddress+":"+port)
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}
           

② Java High Level REST

@Autowired
    RestHighLevelClient elasticsearchClient;
    public static final String TEST_PRODUCT = "kikuu_test_product";
    
    /**
     * add product
     * 其實可以使用批量插入的。
     */
    @Test
    void addDocument() throws IOException {
        IndexRequest request = new IndexRequest(TEST_PRODUCT);
        List<ESProduct> productList = getProductList();
        for (ESProduct each : productList) {
            request.id(each.getId());
            request.source(new Gson().toJson(each), XContentType.JSON);
            elasticsearchClient.index(request, RequestOptions.DEFAULT);
        }
    }

    /**
     *  add child_doc:activity
     */
    @Test
    void addDocumentActivity() throws IOException {
    	IndexRequest request = new IndexRequest(TEST_PRODUCT);
        List<ESPromotion> promotionList = common.getPromotion();
        request.id(promotionList.get(1).getId());
        request.source(new Gson().toJson(promotionList.get(1)), XContentType.JSON);
        elasticsearchClient.index(request, RequestOptions.DEFAULT);
        System.out.println(new Gson().toJson(promotionList.get(1)));
        System.out.println(promotionList.get(1).toString());
    }

    /**
     * delete _doc ,
     */
    @Test
    void deleteDocById() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest(TEST_PRODUCT, "1");
        // 删除子文檔需要指定 routing
        //deleteRequest.routing("1");
        DeleteResponse response = elasticsearchClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(response.getIndex());
        System.out.println(response.status());
        System.out.println(response.toString());
    }
    
    /**
     * search child_doc [promotion] by activityId
     * 滿足某個條件删除
     */
    @Test
    void searchDocByKeyword() throws IOException {
        SearchRequest searchRequest = new SearchRequest(TEST_PRODUCT);
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("activityId", "1212420");
        searchBuilder.query(termQueryBuilder);
        searchRequest.source(searchBuilder);

        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(jsonTransferESPromotion(searchResponse.toString()));
    }

    /**
     * search product
     * 按某個條件查詢 product 并轉成對象
     */
    @Test
    void searchESProduct() throws IOException {
        SearchRequest searchRequest = new SearchRequest(TEST_PRODUCT);
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        searchBuilder.query(QueryBuilders.matchQuery("productType", "product"));
        searchBuilder.size(100);

        searchRequest.source(searchBuilder);
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        // ES Object resolving To ESProduct
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        List<ESProduct> list = new ArrayList<>(120);
        int count = 1;
        System.out.println("<==========================================================     _doc     ==========================================================>");
        for (SearchHit hit : searchHits) {
            String sourceAsString = hit.getSourceAsString();
            // 單個字元串轉對象.
            ESProduct esProduct = new Gson().fromJson(sourceAsString, ESProduct.class);
            list.add(esProduct);
            System.out.println("The " + (count++) +  " product information:" + esProduct.toString());
        }
    }
    
   /**
     * search product filter child _doc
     * when you write query, you should write it first.
     * 查詢店鋪正常 且目前時間在的活動時間内的商品,
     * 關系含義
     * eq =, neq !=, gt >, gte >=, lt <, lte <=,
     * 過濾多個子文檔查詢
     */
    @Test
    void searchProductById() throws IOException {
    	SearchRequest searchRequest = new SearchRequest(TEST_PRODUCT);
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        // 過濾掉 不包含 promotion 的父文檔
        BoolQueryBuilder promotionFilter = QueryBuilders.boolQuery();
        promotionFilter.filter(QueryBuilders.rangeQuery("startDate").lte(new Date().getTime()));
        promotionFilter.filter(QueryBuilders.rangeQuery("endDate").gte(new Date().getTime()));
        HasChildQueryBuilder hasChildPromotion = new HasChildQueryBuilder(SearchChildDocType.KIKUU_TEST_PRODUCT_CHILD_DOC_PROMOTION.child, promotionFilter, ScoreMode.Avg);
        hasChildPromotion.innerHit(new InnerHitBuilder().setExplain(true));
        QueryBuilder queryBuilderPro = hasChildPromotion;

        // 過濾掉 不包含 store 的父文檔
        BoolQueryBuilder storeFilter = QueryBuilders.boolQuery();
        storeFilter.filter(QueryBuilders.termQuery("storeStatus", 20));
        HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder(SearchChildDocType.KIKUU_TEST_PRODUCT_CHILD_DOC_STORE.child, storeFilter, ScoreMode.Avg);
        hasChildQueryBuilder.innerHit(new InnerHitBuilder().setExplain(true));
        QueryBuilder queryBuilderStore = hasChildQueryBuilder;

        BoolQueryBuilder outFilter = QueryBuilders.boolQuery();
        outFilter.filter(queryBuilderPro).filter(queryBuilderStore);

        searchBuilder.query(outFilter);
        searchRequest.source(searchBuilder);
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("\n============================================================\n");
        System.out.println(searchResponse.toString());
    }
           
官方文檔還是給力,寫的好。

總結 :所有用請求可以實作的查詢條件都可以用代碼來實作。

2. other Client。

其他版本請檢視官方文檔,都有詳細介紹,這裡就不一一贅述了

繼續閱讀