### Ghi chú kỹ thuật: Hiểu về khái niệm Hstore trong OpenStreetMap & PostGIS

### 1. Vấn đề cốt lõi của dữ liệu OpenStreetMap (OSM)

Dữ liệu OpenStreetMap cực kỳ linh hoạt và đa dạng. Một địa điểm (POI) trên bản đồ có thể có rất nhiều thuộc tính khác nhau: 

* Một **nhà hàng** sẽ có các thuộc tính: amenity=restaurant, name=Phở Thìn, cuisine=vietnamese, opening_hours=06:00-22:00.
* Một **trạm sạc xe điện** lại có các thuộc tính: amenity=charging_station, capacity=8, voltage=220, operator=VinFast.

Nếu thiết kế cơ sở dữ liệu quan hệ (RDBMS) kiểu truyền thống, bạn sẽ phải tạo hàng trăm cột cho một bảng để chứa tất cả các thuộc tính có thể có trên đời. Việc này làm database cực kỳ phình to, trống rỗng (nhiều ô bị NULL) và truy vấn rất chậm. 

### 2. Giải pháp Hstore là gì?



**hstore** là một tiện ích mở rộng (Extension) của PostgreSQL. Nó cho phép bạn lưu trữ một tập hợp các cặp **Khóa - Giá trị (Key - Value)** ngay trong **một cột duy nhất**. 

Thay vì tạo nhiều cột, tất cả các thuộc tính phụ, lạ hoặc ít dùng của OpenStreetMap sẽ được nén gọn lại vào một cột duy nhất (thường đặt tên là tags). 

**Ví dụ trực quan về cách lưu trữ trong cột tags kiểu hstore:**
"amenity"=>"restaurant", "cuisine"=>"vietnamese", "name"=>"Phở Thìn", "opening_hours"=>"06:00-22:00" 


### 3. Điều gì vừa xảy ra trong hệ thống của bạn?

1. **Lỗi ban đầu (type "hstore" does not exist):** Khi bạn chạy lệnh osm2pgsql với cờ --hstore, công cụ này cố gắng tạo ra cột tags với kiểu dữ liệu hstore để gom tất cả các thuộc tính của khu vực Hà Nội lại. Tuy nhiên, PostgreSQL mặc định tắt tính năng này để tiết kiệm tài nguyên, dẫn đến việc nó không hiểu kiểu dữ liệu hstore là gì và báo lỗi.
2. **Khi bạn chạy lệnh CREATE EXTENSION:** Lệnh này đã kích hoạt "siêu năng lực" hstore cho cơ sở dữ liệu osm_db.
3. **Khi nạp lại thành công:** osm2pgsql đã tách các thuộc tính quan trọng nhất (như name, highway, landuse) ra các cột riêng để Martin và Nominatim truy vấn cho nhanh. Còn toàn bộ các thuộc tính "râu ria" khác của Hà Nội, nó ném hết vào cột tags (kiểu hstore). Bạn không bị mất bất kỳ một mẩu thông tin thô nào từ OpenStreetMap gốc.

### 4. Lợi thế cực lớn của hstore đối với Martin (Bản đồ nền)

Nhờ có cột hstore này, **Martin tile server** có một lợi thế vô địch: **Tùy biến bản đồ không giới hạn mà không cần nạp lại DB.** 

Ví dụ, nếu một ngày bạn muốn làm một bản đồ hiển thị riêng các quán ăn có thuộc tính cuisine=vietnamese. Bạn không cần phải chỉnh sửa cấu trúc bảng của PostGIS, cũng không cần nạp lại file .pbf. Bạn chỉ cần viết một câu lệnh SQL lọc trực tiếp trong cấu hình của Martin: 

sql

SELECT way, name FROM planet_osm_point WHERE tags->'cuisine' = 'vietnamese';

Hãy thận trọng khi sử dụng mã.

Dấu -> là cú pháp đặc biệt của PostGIS giúp bạn "móc" dữ liệu cực nhanh từ trong cột hstore ra để dùng.




# cần phải cấu hình hstore cho postgres 
docker exec -it gis_postgis psql -U admin -d osm_db -c "CREATE EXTENSION IF NOT EXISTS hstore;"
