Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer

[Tutorial] Build simple geoserver query CQL form

Cái Video này làm mấy ngày rồi, nhưng giờ mới có thời gian bổ sung cho nó hoàn thiện nên viết thành bài luôn

Mọi người xem Video hướng dẫn chi tiết nhé.

Về cơ bản thì cái này chỉ tìm kiếm dựa trên cú pháp truy vấn CQL được GeoServer hỗ trợ. Còn ai không biết CQL là gì, dùng thế nào thì xem video hoặc vào link đưới

http://docs.geoserver.org/stable/en/user/tutorials/cql/cql_tutorial.html

Trong video hướng dẫn chi tiết từ bước tạo form tìm kiếm đến xử lý giá trị người dùng nhập vào form để truy vấn và hiện kết quả.

https://dothanhlong.org/demo/geoserver_query/

Giờ mình không ghi lại những gì có trong video nữa, mình sẽ đi vào phần chỉnh sửa, bổ sung nâng cao xíu cho chức năng thêm hoàn thiện.

Hoàn thiện chức năng tìm kiếm cơ bản với GeoServer CQL query

Ở video, mình đã hướng dẫn tìm kiếm được đối tượng và hiển thị đối tượng. Tuy nhiên, vẫn còn một số hạn chế như:

  1. Việc tìm kiếm mình dùng phép “LIKE“, phép tìm kiếm LIKE yêu cầu người dùng nhập từ khóa tìm kiếm phân biệt chữ hoa và chữ thường. Mình sẽ hướng dẫn dùng phép tìm kiếm khác giúp người dùng dễ dàng trong việc tìm kiếm hơn.
  2. Kết quả chỉ hiển thị ra đối tượng cần tìm kiếm nên người dùng vẫn sẽ không biết được vị trí chính xác của đối tượng đó nằm ở khu, vùng nào trên bản đồ tổng thể. Ở bước hướng dẫn này, mình sẽ thêm cái bản đồ tổng thể vào để biết vị trí cái kết quả tìm kiếm của mình nằm ở đâu.
  3. Bên cạnh đó, việc nhấp nút tìm kiếm xong kết quả nhảy sang trang khác cũng khá bất tiện, mình sẽ hướng dẫn áp dụng Ajax để hiển thị kết quả luôn trên trang tìm kiếm.

Nâng cấp chức năng tìm kiếm không phân biệt chữ hoa, chữ thường.

Đối với phép tìm kiếm LIKE trong CQL (cả trong PostgreSQL) thì nó sẽ phân biệt chữ viết hoa và chữ viết thường.

Ví dụ 2 câu truy vấn bên dưới:

tentinh LIKE ‘%Nghệ%’

tentinh LIKE ‘%nghệ%’

2 câu truy vấn này sẽ cho 2 kết quả khác nhau mặc dù chỉ khác nhau chữ N viết hoa và chữ n viết thường.

tentinh LIKE ‘%Nghệ%’ sẽ trả về kết quả là Nghệ An (Do trong bảng thuộc tính dữ liệu mình lưu là Nghệ An)

tentinh LIKE ‘%nghệ%’ sẽ trả về kết quả là không tìm thấy do trong bảng thuộc tính dữ liệu không có giá trị nào mình lưu bắt đầu bằng chữ nghệ hết.

Nhưng đối với người dùng thị họ đâu biết là mình lưu trong dữ liệu là viết hoa hay viết thường, nên mình cũng không thể bắt buộc họ phải viết đúng theo mình thì mới tìm được kết quả :’)

Vì vậy, CQL có hỗ trợ một kiểu tìm thứ 2 là ILIKE. Kiểu này cho phép tìm kiếm không phân biệt chữ hoa hay chữ thường.

Đối với ILIKE thì 2 câu truy vấn ở trên đều trả về kết quả là Nghệ An cả. Vẹn cả đôi đường :v

Vậy chúng ta sẽ sửa các chỗ LIKE phần xử lý yêu cầu truy vấn do người dùng nhập vào ở file xuly.php thành ILIKE hết.

Lúc đó sẽ thành:

$cql=”NAME_2 ILIKE ‘%”.$txttentinh.”%’ AND NAME_1 ILIKE ‘%”.$txttenkhuvuc.”%'”;

Thêm bản đồ tổng thể vào kết quả tìm kiếm

Hiện tại thì sau khi tìm kiếm. Ví dụ tìm tỉnh Nghệ An, chúng ta sẽ được kết quả như sau:

geoserver bản đồ tỉnh Nghệ An
geoserver bản đồ tỉnh Nghệ An

Haha, nhận được kết quả thế này thì biết hình dáng tỉnh Nghệ An đó, cơ mà không biết nó nằm ở đâu =))

Thế thì phải làm thế nào đây?

Mình có một tối kiến là chúng ta sẽ style một cái bản đồ màu tối tối. Để nó nằm dưới kết quả tìm kiếm. Cái bản đồ tìm kiếm của mình thì mình đã style “7 màu” rồi nên chắc chắn nó sẽ nổi lên trên cái bản đồ nền kia. Giống thế này:

geoserver bản đồ tỉnh Nghệ An
geoserver bản đồ tỉnh Nghệ An

Ok, bắt tay làm thôi.

Chuẩn bị một tấm hình làm bản đồ nền.

Điều kiện tiên quyết của cái bản đồ nền là là nó phải cùng kích thước với cái bản đồ kết quả. Vậy làm sao để có cái bản đồ cùng kích thước?

Đơn giản nhất là chúng ta cũng xuất từ GeoServer ra rồi save lại thành tấm hình là được.

Vào GeoServer, để style lớp bản đồ lại thành mặc định (polygon)

Kết quả khi preview sẽ như hình dưới:

Bản đồ nền Việt Nam
Bản đồ nền Việt Nam

http://dev.dothanhlong.org:8080/geoserver/dothanhlong/wms?service=WMS&version=1.1.0&request=GetMap&layers=dothanhlong:vn_provinces&styles=&bbox=102.066223144531,7.31143283843994,117.895713806152,23.4724426269531&width=752&height=768&srs=EPSG:4326&format=application/openlayers

Giờ chúng ta sẽ save hình này lại để làm bản đồ nền với tên là

dothanhlong-vn_provinces.png

http://dev.dothanhlong.org:8080/geoserver/dothanhlong/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=dothanhlong%3Avn_provinces&STYLES&SRS=EPSG%3A4326&WIDTH=752&HEIGHT=768&BBOX=101.71142578125%2C6.96533203125%2C118.23486328125%2C23.84033203125

Sửa file xuly.php đề chèn bản đồ nền vào

Để chèn hình vào thì chúng ta cũng echo thẻ img như đối với kết quả tìm kiếm

echo ‘<img src=”dothanhlong-vn_provinces.png”>’;

Tuy nhiên, để hình nền nằm phía sau kết quả thì chũng ta phả echo hình ra trước, sau đó mới đến kết quả vì mặc định code php sẽ đọc và thực thi từ trên xuống dưới.

Sửa file xuly.php đề chèn bản đồ nền vào
Sửa file xuly.php đề chèn bản đồ nền vào

Kiểm tra kết quả

Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer
Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer

Kết quả sẽ bị lệch với ảnh nền vì hiện giờ trình duyệt Web hiểu là mình đang hiển thị 2 hình kế bên nhau. Do vậy phải style css thẻ img của kết quả lại. Chúng ta dùng thuộc các thuộc tính sau:

position: Khai báo loại vị trí

left: Canh lề trái

top: Canh lề trên

Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer
Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer

Chúng ta tiếp tục canh chỉnh top và left sao cho vị trí Nghệ An trong hình khớp với Nghệ An trên bản đồ nền. Có được 2 thông số top, left rồi thì khai báo vô file xuly.php

Lưu lại và kiểm tra kết quả

Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer
Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer

Giờ chúng ta có thể thử tìm kiếm với các tỉnh khác

Bản đồ Bắc Trung Bộ và Nam Trung Bộ
Bản đồ Bắc Trung Bộ và Nam Trung Bộ
Bản đồ Bắc Trung Bộ và Nam Trung Bộ
Bản đồ Bắc Trung Bộ và Nam Trung Bộ

Sử dụng kỹ thuật Ajax trong hiển thị kết quả tìm kiếm bản đồ

Hiện tại ứng dụng của chúng ta đang thưc hiện gửi, nhận kết quả theo hình thức Form GET bình thường. Hạn chế của chế độ mặc định khi submit form này là kết quả sẽ được hiển thị ở một trang khác (trang xuly.php) khi chúng ta submit gửi dữ liệu.

Vậy để hiển thị kết quả ngay bên dưới form tìm kiếm thì thể nào?

Chúng ta có một kỹ thuật gọi là kỹ thuật Ajax. Kỹ thuật này cho phép gửi, nhận dữ liệu trên cùng một trang, mọi yêu request đều được thực hiện “ngầm”

Để sử dụng thì bắt buộc phải biết Javascript. Xem bài sau về gọi Ajax bằng Jquery:

Get Method Ajax

Ở đây mình mặc định là các bạn biết Javascript rồi nhé!

Bắt tay nào!

Sửa file chứa form tìm kiếm (index.html)

Ở file này, do chúng ta sử dụng Bootstrap để thiết kế form nên chúng ta đã khai báo sẵn luôn thư viện Jquery, không cần khai báo lại :v

Khai báo jquery
Khai báo jquery

Xác định vị trí hiển thị kế quả trên form

Mình cho hiện kết quả bên dưới form tìm kiếm, như sau:

Hiện kết quả bằng Ajax
Hiện kết quả bằng Ajax
Hiện kết quả bằng Ajax
Hiện kết quả bằng Ajax

Thêm đoạn Javascript gọi Ajax đến file xuly.php

Thêm đoạn Javascript gọi Ajax đến file xuly.php
Thêm đoạn Javascript gọi Ajax đến file xuly.php

Trong đó lưu ý data truyền đi sẽ là 2 giá trị trong 2 textbox có id là:

txttenkhuvuc

txttentinh

File để xử lý các kết quả vẫn là file xuly.php

Kết quả được trả về sẽ được hiển thị ở thẻ div có id là kq

Thêm sự kiện để gọi Ajax

Chúng ta đã có một nút bấm submit để tìm kiếm theo cách thông thường.

Bây giờ để gọi Ajax, chúng ta cần tạo một nút khác với sự kiện click chuột vào sẽ gọi cái hàm Ajax của chúng ta khai báo ở trên

Thêm sự kiện để gọi Ajax
Thêm sự kiện để gọi Ajax

Vậy là xong, save lại và test

Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer
Hướng dẫn xây dựng chức năng tìm kiếm đơn giản cho GeoServer

Ồ, kết quả lại bị nhảy, lý do là lúc nãy chúng ta canh style left và top khi không có form ở bên trên, giờ chúng ta phải cộng thêm chiều cao của form vào nữa thì nó mới đúng. Cũng canh chỉnh giống khi nãy đến khi như ý^^

Và kết quả cuối cùng

https://dothanhlong.org/demo/geoserver_query/v2/

Tìm kiếm với từ khóa tỉnh Nghệ An

GeoServer tìm kiếm với từ khóa tỉnh Nghệ An
GeoServer tìm kiếm với từ khóa tỉnh Nghệ An

Tìm kiếm với khu vực Tây Nguyên

GeoServer Tìm kiếm với khu vực Tây Nguyên
GeoServer Tìm kiếm với khu vực Tây Nguyên

Vậy là xong!

Hi vọng T, H và mọi người làm được, kaka

P/s: Cái này chỉ toàn kiến thức cơ bản thôi đấy :p

-soiqualang_chentreu-