---
# System prepended metadata

title: L2H-HW

---

# L2H-HW

## 1. The query you use to setup the index settings
### ANS:
#### Create Index
##### Command
<pre><code>PUT /jobs
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  },
  
  "mappings": {
    "properties": {
      "Name": { "type": "text" },
      "Job": { "type": "text" },
      "Age": { "type": "integer" },
      "Gender": { "type": "text" }
    }
  }
}</code></pre>
#### Check settings are working
##### Command
<pre><code>GET _cat/shards?h=index,shard</code></pre>
##### Result
![](https://i.imgur.com/xnXe4Vt.jpg)
## 2. Screenshot of the index settings and the screenshot of the dashboard you created.
### ANS
#### My Sample Index: Jobs
![](https://i.imgur.com/qu6z7J6.jpg)
#### Dashboard made by data sources including amazon.books.json and steam.games.json
![](https://i.imgur.com/S8ydk1X.jpg)
## 3. Details of how you process the data
### ANS
我將這個 Load資料的過程分成三個部分包含單次跟批次處理，最後一段則是使用第二份遊戲的資料。

#### Stage 1. Single Test
1. 先將 Repository Clone下來，確認資料的長相，我複製了一份檔案，擷取了 **_id** = 1 的 document做測試。
1. 選擇用 Python API json講文字轉換成 Json，在確認可行性的過程中有遇到引號需要跳脫，用 Replace處理。
1. 最後確認此資料 amazon.books.json可以被轉換成 431個 Document(Dictionary)。
1. 為了先得到一個動態生成的 Mappings，使用 Elasticsearch的 API 傳入一個 Document。
1. 由於先前用 Dev Tool測試，得知 **_id**是 Metadata Field，塞入資料時會觸及 Error，根據 API引數說明，可以代在 Function裡面，所以在 輸入資料前將 **_id** POP出來再執行。<pre>document.pop("_id")
es.index(index='test_1',body=document,id=cnt)</pre>
3. 用 Dev Tool取得 mappings，看起來有一個 **pageCount**可以改 Interger，另外有嘗試調整 **publishedDate**但發生了一些問題，會在最後一題說明。
4. 基本上可以確定資料是可以進行寫入。

#### Stage 2. Batch Insert

1. 拿到 Notepad++檢視一下字元符號，得到訊息"} {"可能可以將document彼此隔開。
1. 將檔案讀入，用觀察到的 "} {"去分隔成為 list，檢視每個 Element，將括號補齊。
1. 根據時間複雜度，將跳脫字元 replace的步驟改放到開檔的時候做一次性處理，測試也沒問題。
1. 最後確認筆數與 **_id**的 Distinct Count是相同的，但是 **_id**在第400個 Document看起來像外部 Key的 Format，但在這邊因為有 pop掉原本的 id，另外補上一個 auto-increment的數字，所以暫時沒有探討。
1. 確認 json在 Python裡面可以成為 Dictionary物件之後，查看每個 Dictionary的 Keys都沒有下底線開頭所謂的 Metadata Field，資料面確認就到這邊。
1. 使用 Elasticsearch7的 API進行 POST，完成。
1. 從 Dev Tool GET Count數為431， Discovery檢視一下資料本身，看起來無異常。
1. 到 Stack Management產生 Index Pattern，因為 **publishedDate**的範圍太大，沒有特地加入 timestamp，接下來就開始使用資料視覺化。

#### Stage 3. Source **steam.games.json**

1. 由於這份資料不需要前處理就可以轉換成 Json，所以我這邊就直接 Load成 Dictionary，不過從資料上看來，他應該是一個回傳的 Payload，所以就先取 Respondes中的 Games的內容。
1. 觀察一個 Field **appid**其 Value是否為不可重複，將 appid串成 list，利用 list 轉 set之後，會消除重複值，比較 List跟 Set的 Length是否相同，確認都為192， Document也為相同筆數192，所以先用 appid暫時當作 id。
1. 將一筆資料 POST到 ES，確認 Mappings沒有太大問題，因為同樣 **_id**會自行增加一個 Version並且更新，所以就沒特別去刪除這一筆，就直接 Batch輸入，
1. 從 Dev Tool GET Count數為192， Discovery檢視一下，看起來無明顯異常。
1. 到 Stack Management產生 Index Pattern，開始使用資料視覺化。

## 4. The query you use to find out the total of flight delay
### ANS
```
GET kibana_sample_data_flights/_count
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "FlightDelayMin": {
              "gte": 1
            }
          }
        }
      ]
    }
  }
}
```
## 5. What problem you facing during the entire practice and how you solve 
### ANS
#### 無法在 Visualization選到 Integer類別的 Field
> * 我自己手動做了一些資料，在進行視覺化的時候遇到了這個問題，因為 Field Data Type怎麼改都沒有成功，我試著用 Discover觀察資料，發現多了一筆 Settings相關的資訊如下圖，檢視 Mappings覺得內容過於複雜，不太正常。
> ![](https://i.imgur.com/fe7PGQs.jpg)
> * 用動態產生 Mappings的方式直接建出 Index，比較兩者之後，確認原先的 Mappings是異常的，Field Data Type也不如我預期，這邊判斷 Settings不應該被視為一個 Document，而且看起來這個 Mappings是包了好幾層，所以推斷應該是整段 Create的 Command都被當成一個 Document PUSH進去。
> * 於是回頭確認官方文件，確定一件事， Create Index是用關鍵字 PUT，另外也測試 PUT是否可以針對 Type，答案是不可行，PUT到 Type層級也確定是找不到 Method的。
> * 這是原先錯誤的 Command。
```
POST /try_1/man
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  },
  
  "mappings": {
    "properties": {
      "Name": { "type": "text" },
      "Job": { "type": "text" },
      "Age": { "type": "integer" },
      "Gender": { "type": "text" }
    }
  }
}
# 更正後
PUT /try_1
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  },
  
  "mappings": {
    "properties": {
      "Name": { "type": "text" },
      "Job": { "type": "text" },
      "Age": { "type": "integer" },
      "Gender": { "type": "text" }
    }
  }
}
```
#### 承上，重塞資料的時候出現錯誤
```{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "Rejecting mapping update to [l2h_sample] as the final mapping would have more than 1 type: [_doc, man]"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "Rejecting mapping update to [l2h_sample] as the final mapping would have more than 1 type: [_doc, man]"
  },
  "status" : 400
}
```
> 由於先前測試，指定了 Type的名稱，在 _search資料的時候遇到下面的 Error，想到課堂聽到 Type在不同版本有改特性，查找官網這版對於 Type的設定，結果， Type必須要 Single才會正常運作，而實際上 Default會給 **_doc**這樣的名稱，看 Youtube上一些外國人示範簡單的 Query也會在 GET的時候主動加上 **_doc**，所以將 Index刪除重新建立，讓 Type唯一。 

#### 重新建立 Index，透過 Discover確認資料都正確無誤之後， Visualization還是選取不到 Integer類別的欄位
> 因為發現 Visualization能夠選擇用來 Aggregation的 Field還是跟之前一樣沒有變化，映像中設定 Index Pattern的時候，是一種預前宣告給 GUI用的動作，懷疑是這邊設定沒有更新，所以從 Stack Management裡面確認，跟 Console查詢得到的 Mappings結果不一樣，於是 Refresh Index Pattern解決這個問題。
#### 用 python內建的 json.loads去讀取一個 Document字串的時候，出現以下錯誤一
```
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
```
> 檢查 json的 Source Code確認他會對 File的文檔，用 Regular Expression，比對跟成對有關的規則，在這個時候就已經發生錯誤，原因是有雙引號或單引號不成對，這點用 Replace的方式加上跳脫符號處理。
```
_m=STRINGCHUNK.match，STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS))
```
#### 用 python內建的 json.loads去讀取一個 Document字串的時候，出現以下錯誤二
```
json.decoder.JSONDecodeError: Extra data: line 15 column 2 (char 2517)
```
> 將文檔貼到 Notepad++檢查 Char 2517，發現在用"} {" split文檔的時候，會缺大括弧，所以設定了一些頭尾判斷補齊。
#### 使用Python Elasticsearch API的時候， Port參數不存在
> 為了測試 API的基本功能，我先根據 IThome讀到的教學 Fork了一個 docker-compose在自己的 VM，先用 API直連預設的 9200 Port，但報錯，提示是不存在這個參數，尋找解答的時候，有文章提及 ES在新舊版差異很大，甚至在雲服務化後很多框架都有重新改版，我將 Error拿到 Stack Overflow，得到一些解答，高於7.14的 API都會跟我用的版本有不相容的問題，所以去檢查 pip3安裝的 API版本，看起來是最新的，果然不合用，使用 pip3降版，選擇跟 AWS Opensearch創建 Doamin時一樣的版本，7.10，測試連線成功，之後再改成連到 AWS，使用 URL跟一開始創建設定的帳號密碼進行當作引述進行明碼連線，成功取得 ES的訊息。
#### 在輸入 amazon.books.json資料時，時間格式的 Field報錯
```
elasticsearch.exceptions.RequestError: RequestError(400, 'mapper_parsing_exception', "failed to parse field [publishedDate.$date] of type [date] in document with id '-z-hDoEBMNMOjQaujx-d'. Preview of field's value: '2009-04-01T00:00:00.000-0700'")
```
> 因為想讓時間的 Format好看一點，所以在這個 Field加上了 Format yyyy-MM-dd並建立 Index，結果發生錯誤，研究官網，這個宣告，其實是一種 Parsing Rule，宣告之後就要照他的方式 Feed資料，測試了官方給的 Sample，他是用各種不同的 Format輸入到同一個 Index， 官方提供的 Mappings因為沒有對 date的 Parsing Rule設限，所以他示範的幾種格式都可以正常輸入到同一個 Index，也就是說，ES當你沒有設定 Parsing Rule的時候，他會動態解析 Data，然後在背後用相同的方式儲存。
```PUT my-index-000001
{
  "mappings": {
    "properties": {
      "date": {
        "type":   "date",
        "format": "yyyy-MM-dd" # 因為這個宣告導致 Parsing Rule被固定下來效果
      }
    }
  }
}
```
#### 承上，重新建立 Index跟輸入資料之後，在 Visualization看不到資料
> Index Pattern建立的時候，因為把 publishedDate設定成 timestamp導致剛進入 Dashboad只有選擇最近的15分鐘，以至於看不到資料，因為過去有 Grafana的使用經驗，所以推斷是 Time Range影響到資料的呈現，從資料面檢視，發現書本出版跨的年度跨太多年，這樣 Time Ranger會選的非常大，所以取消 Timestamp，以方便這次的作業，但在 Flight的資料集有用到。