iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
Software Development

用 Golang + Elasticsearch + Kubernetes 打造雲原生搜尋服務系列 第 20

Day 20 - Bulk 匯入 5–10 萬筆 (以 Jeopardy 資料集為例)

  • 分享至 

  • xImage
  •  

昨天我們處理搜尋的分頁方案,避免 from+size 帶來的效能問題。接下來要做的,就是把一個「真正規模」的資料集放進 Elasticsearch,讓我們能實際測試效能。

從 Kaggle 挑選公開資料集:Jeopardy! 問答題庫,包含數十萬筆問題、答案、金額,適合當作搜尋的題材。


Step 1 — 資料準備

Kaggle 下載資料集 JEOPARDY_CSV.csv,我們只需要幾個欄位:

  • Question:題目
  • Answer:正解
  • Category:題目所屬分類
  • Value:題目的分數(難度指標)

我們先寫個小工具,把 CSV 轉成 Elasticsearch Bulk API 格式

package main

import (
	"encoding/csv"
	"encoding/json"
	"log"
	"os"
	"strconv"
)

type Jeopardy struct {
	Question string `json:"question"`
	Answer   string `json:"answer"`
	Category string `json:"category"`
	Value    int    `json:"value"`
}

func main() {
	f, err := os.Open("JEOPARDY_CSV.csv")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	reader := csv.NewReader(f)
	records, err := reader.ReadAll()
	if err != nil {
		log.Fatal(err)
	}

	out, _ := os.Create("bulk_jeopardy.ndjson")
	defer out.Close()

	for i, row := range records {
		if i == 0 { // skip header
			continue
		}
		value := 0
		if row[3] != "" {
			val, err := strconv.Atoi(row[3])
			if err == nil {
				value = val
			}
		}
		doc := Jeopardy{
			Question: row[1],
			Answer:   row[2],
			Category: row[3],
			Value:    value,
		}
		meta := map[string]map[string]string{
			"index": {"_index": "jeopardy"},
		}
		mj, _ := json.Marshal(meta)
		dj, _ := json.Marshal(doc)

		out.Write(mj)
		out.Write([]byte("\n"))
		out.Write(dj)
		out.Write([]byte("\n"))
	}
}

這樣會輸出一個 bulk_jeopardy.ndjson,裡面長這樣:

{"index":{"_index":"jeopardy"}}
{"question":"For the last 8 years of his life, Galileo was under house arrest for espousing this man's theory","answer":"Copernicus","category":"HISTORY","value":200}
{"index":{"_index":"jeopardy"}}
{"question":"The city of Yuma in this state has a record average of 4,055 hours of sunshine each year","answer":"Arizona","category":"GEOGRAPHY","value":400}

Step 2 — Bulk 匯入 Elasticsearch

Bulk API 可以用 curl 直接送:

curl -H "Content-Type: application/x-ndjson" -XPOST "localhost:9200/_bulk?pretty" --data-binary "@bulk_jeopardy.ndjson"

如果檔案有十幾萬筆,可以分批(例如 5000 筆一批)送進去,避免請求太大。


Step 3 — 驗證資料

匯入後,可以測試一下:

curl "localhost:9200/jeopardy/_count"

預期應該會有 20 萬筆以上。

還可以做個簡單的查詢,例如找關於「Shakespeare」的題目:

curl -X GET "localhost:9200/jeopardy/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "question": "Shakespeare"
    }
  }
}
'

小結

到這裡,我們終於把一個「真實規模」的資料集放進 Elasticsearch,完成了 Day 20 的目標
這不只是練習 API,而是讓我們的搜尋服務 可以被實際驗證

從這一步開始,我們有了基礎:

  1. 昨天學的 分頁方案可以在 Jeopardy 題庫上跑跑看
  2. 之後還能壓測效能、觀察資源使用,模擬真實系統的工作量

上一篇
Day 19 - 分頁方案:換成 `search_after`
下一篇
Day 21 - 參數優化:讓 Jeopardy! 索引快起來
系列文
用 Golang + Elasticsearch + Kubernetes 打造雲原生搜尋服務30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言