thắc mắc Gom các tiêu chuẩn Sort vào một Long?

  • Người tạo chủ đề Người tạo chủ đề 4nh7i3m
  • Ngày bắt đầu Ngày bắt đầu

4nh7i3m

Senior Member
Chào mọi người,

Mình có một bài toán về hiển thị thế này muốn tham khảo ý kiến mọi người xem giải quyết thế nào cho đúng.

1. Mình có một hệ thống Elastic Search trong đó có 1 index Products.

2. Bên ngoài Web Frontend sẽ hiển thị index Products này với 4 tiêu chuẩn: default, sản phẩm mới nhất, giá giảm dần, giá tăng dần.

3. Trong mỗi tiêu chuẩn sort nó lại phân thành nhiều tiêu chuẩn phức tạp khác.
Ví dụ:
Default:
  • SortBy: Các sản phẩm có flag highlight (string) sẽ lên đầu
  • ThenBy vị trí các sản phẩm được xác định qua SortOrder (int)
  • ThenBy các sản phẩm có flag new (bool)
  • ThenBy các sản phẩm có flag available (bool), tức là còn trong kho
...

Giá giảm dần:
  • SortBy: Các sản phẩm có flag highlight (string) sẽ lên đầu
  • ThenBy giá giảm dần
  • ThenBy tình trạng hàng trong kho flag available (bool).


4. Vì lý do Sort rất phức tạp như trên nên mình muốn tìm hiểu xem có cách nào để quy các tiêu chuẩn trên về một dạng Long/Integer rồi lưu vào index. Sau đó chỉ cần áp Sort lên cái field đó thôi.

5. Ví dụ: Tạo Field SortDefault với công thức
(If highlight)*10^6+SortOrder*10^3+ IfNew*10^2+ IfAvailabe

Thì ở Frontend khi Default được chọn thì mình chỉ cần Sort theo cái Field SortDefault trong Elastic Search thôi.

Câu hỏi: Mình nghĩ chắc trong computer science có một cái giải thuật nào đó để build các tiêu chuẩn sort thành một Long/Int value. Nhưng mình lại không biết nó tên gì.

Anh em có ai biết chỉ mình. Mình cám ơn.
 
vậy nếu bạn cần thêm sort criteria thì phải reindex toàn bộ dữ liệu à
 
Vì lý do Sort rất phức tạp như trên nên mình muốn tìm hiểu xem có cách nào để quy các tiêu chuẩn trên về một dạng Long/Integer rồi lưu vào index. Sau đó chỉ cần áp Sort lên cái field đó thôi.

Mục đích cuối cùng của bạn là gì nhỉ. Bạn đang có thắc mắc vì lý do học thuật hay là nó sẽ mang lại cho bạn lợi ích cụ thể nào đó?
 
@nautilux mỗi ngày một lần dữ liệu được import mới vào ES index products_yyyy_mm_dd. Set alias products_latest rồi query thôi. Cần thì rollback lại dữ liệu cũ bằng cách đổi alias về index cũ.

Cho nên, đổi tiêu chuẩn sort thì index phải được cập nhật nếu gom hết chuẩn Sort vào một Field.

@qk_pro đang cần làm cho hệ thống prod. Đang suy nghĩ làm thế nào cho gọn thay vì đưa từng Sort Criteria thành Integer field rồi SortBy.ThenBy.ThenBy thì gom hết vô một lần rồi SortBy thôi.
 
@perepermin hình như tôi không hỏi cách dùng sort function của ES? Hoặc là anh không đọc spec của tôi ghi hoặc là anh cũng chẳng đọc bài của tôi ghi ngoài thả đại cái comment vô thưởng vô phạt.
 
Ví dụ bác có 2 (k) loại sort, mỗi sort có 4 (n) conditions:
1. Default (k = 0)
2. Giá giảm dần (k =1)
Thì thuật toán có thể như sau
4 conditions có giá trị: 2^n - 1 với n bắt đầu = 1
- 1, 2, 4, 8
Giá trị mỗi loại sort sẽ là: 2*k + sum(conditions)
-> Default has max = 15 < 16 (1*2^n)
-> Sort giá giảm has max = 31 ( 2*2^n)

Để xác định loại sort ở back end sẽ là
Mã:
func (longNum)
for ( int i = 1: i <= k; i++) {
    if(longNum < k*2^n) {
        // do search 
    }
}
 
Câu hỏi: Mình nghĩ chắc trong computer science có một cái giải thuật nào đó để build các tiêu chuẩn sort thành một Long/Int value. Nhưng mình lại không biết nó tên gì.

Theo tôi biết thì về mặt thực hành, người ta không làm như thế với sorting vì nó đủ nhanh và tiện lợi với những indexing có sẵn trên các field. Nhờ các indexing này mà giả sử mỗi query sử dụng sort ASC hay DSC on-the-fly đều tương đối nhanh.
Về việc bạn muốn "phẳng hóa" một câu query multi-sort thành 1 single sort. Nó sẽ rơi nhiều hơn vào thuật toán ranking, mà các thuật toán ranking này bạn sẽ phải tự phát triển phần nào chứ không có tích hợp sẵn thuật toán chuyển đổi từ multi-sort sang ranking score
 
@qk_pro chính xác là mình tìm cách ranking kết quả. Giờ có từ khóa rồi mình tìm tiếp.
nó làm được nhưng phải đảm bảo, dữ liệu thêm vào ko chia nhỏ mức độ gần nhau:
gỉa sử có 4 fields A,B,C,D

thì để:


A0 * Ka + B0 * Kb +C0* Kc + D0 * Kd > A1 * Ka + B1 * Kb1+C1* Kc + D1 * Kd

<=> Ka ( A0 - A1) > kb ( B0 - B1) + kc (C0 - C1) + kd (D0 -D1)

phải thoả mãn trường hợp xấu nhất là abs(A0 - A1) là min trong mọi pair.

Nhưng khi thêm dữ liệu mới và có một A11 gần A0 hơn làm cho abs(A00 - A1) bé hơn thì làm bài toán bị sai.
 
@nautilux mỗi ngày một lần dữ liệu được import mới vào ES index products_yyyy_mm_dd. Set alias products_latest rồi query thôi. Cần thì rollback lại dữ liệu cũ bằng cách đổi alias về index cũ.

Cho nên, đổi tiêu chuẩn sort thì index phải được cập nhật nếu gom hết chuẩn Sort vào một Field.

@qk_pro đang cần làm cho hệ thống prod. Đang suy nghĩ làm thế nào cho gọn thay vì đưa từng Sort Criteria thành Integer field rồi SortBy.ThenBy.ThenBy thì gom hết vô một lần rồi SortBy thôi.
Tôi dùng elastics gọi api sort json truyền mảng vào mà nhỉ, nó có thể sort theo nhiều field được. không biết đấy có phải yêu cầu của bạn không?
Match string hightlight đó là tìm kiếm bằng thanh tìm kiếm hả, vậy cho sort theo score (viết match trong query để tăng score)
 
@telbook không đó không phải là yêu cầu của mình. Mình không hỏi cách dùng sort function trong ES. Mình cũng ko hỏi match highlight luôn.

Mình hỏi làm cách nào để gom các sort criteria phức tạp lại thành một Long/Interger value để có thể sort nhanh được.

Còn Sort trong ES là sort chuẩn, không xài được.

Ví dụ 1: Ví dụ kích thước chiều dài sản phẩm là Nullable Int. Giờ bên chuyên môn nói sort tăng dần theo chiều dài nhưng những sản phẩm có chiều dài là null thì đứng cuối cùng. Sort của ES không làm được.

Ví dụ 2: Các sản phẩm được tag với các string là highlight, new, popular,.. Giờ bên chuyên môn yêu cầu đưa các sản phẩm có tag highlight lên đầu. Sort của ES không làm được.

Rồi sort kết hợp ví dụ 1 và ví dụ 2. Vậy đó. Nói chung là một dạng ranking các items trong list như bạn gì đó nêu ở trên.
 
ES có thể làm được yêu cầu này nhé, ý tưởng như bác qk nói, và theo kinh nghiệm sử dụng của mình thì ES nó có support, cũng ko quá cao siêu hay phức tạp gì đâu :)
nhưng bạn cần hiểu 1 điều, bài toán ranking đưa ra các kết quả tương đối, dựa trên relevance score. nó ko giống việc filter đưa ra các kết quả khớp chính xác với yêu cầu

đầu tiên là cần phân biệt là với bài toán của bạn, sort criteria cái nào sẽ tương đương với filter (trả lời đúng sai), cái nào sẽ tương đương với query (kết quả tương đối, chính bài toán là ranking)
tiếp theo cái quan trọng nhất là việc sử dụng boost (hàm cộng) hoặc field weight hoặc function score với các query clauses để tác động đến score.
hầu hết các query trong ES mặc định sẽ là boost vào score (tăng giảm score theo hàm cộng), nhưng 1 số query đặc biệt có thể làm nhiều hơn, như function score (define cả 1 hàm toán học với rất nhiều mode với score: cộng trừ nhân chia max min avg), script score... (phang cả 1 đoạn code tính score vào ES query luôn nhé https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html).

VD việc sort by giá giảm dần thì lấy giá * score, hoặc giá tăng dần thì lấy score/giá

sau đó thì tuning dần dần thôi để đạt ranking như mong muốn, tùy thuộc vào mức độ ưu tiên các query mà tính công trừ nhân chia như nào cho hợp
 
Sửa lần cuối:
@4nh7i3m À quy lại bài toán của bạn là muốn query dữ liệu, rồi sort theo score
Bạn có thể check Multi-match query và Boosting query
Hoàn toàn không cần phải boost lúc index. Elastic cũng không khuyến khích
1680908707033.png


Chắc bạn muốn hỏi công thức cộng trừ score? Cái này phải tự tuning thôi vì không có dữ liệu mẫu.
Tư tưởng như bác trên nói. Điều kiện cái nào cần lên đầu thì boost score lên. Nếu dữ liệu chỉ là flag boolean thì dễ, cứ có true/false là cho lên. Flag nào ưu tiên hơn thì query boost nhiều hơn là lên đầu.

kích thước chiều dài sản phẩm là Nullable => Null không có index nên nếu bạn muốn sort thì bạn có thể dùng query exists để boost score
 
Sửa lần cuối:
@perepermin thôi mời ông biến dùm khỏi thread. Đừng trả lời tôi nữa cám ơn. Nếu dùng sort API thì cần gì brain storming, có câu lải nhải hoài.

@vinhomn function_score thì tôi biết và đang áp dụng cho bên Full Text Search. Vấn đề của function_score ở đây là dựa trên weight, functions, query và match trên giá trị tương đối theo ES. Áp dụng vào Full Text Search nó hợp lý vì mình không biết người dùng họ search cái gì? Và mình phải tunning sao cho kết quả ra tương đối phù hợp.

Còn ở đây tui biết rõ 100% phải sort thế nào ( không có query theo từ khoá), chỉ đơn giản là có một danh sách products và nhiệm vụ là hiển thị theo các criteria đưa ra mà thôi.

Ví dụ: Hiển thị danh sách cần cẩu thuộc dòng ABCD hoặc tủ lạnh thuộc dòng XYWZ.

Ngoài ra, function_score thì phải giải quyết bài toán criteria với giá trị null hoặc boolean với giá trị false thế nào? Bắt buộc là phải script. Mà script thì quay trở lại như tui mô tả ở trên là có thuật toán nào để gom các criteria thành một Lòng/Integer hay không?

@telbook Như mình trả lời ở trên, khi đã script là cần giải thuật nên đã giải thích ở trên là mình không biết trong Computer Science có giải thuật nào để gom các sort criteria thành một Long/Interger không?

Hiện tại đang dùng tạm ý tưởng là mỗi sort criteria (if string, if bool, if null, date...) sẽ reflect thành một Field Interger trong document. Rồi sortby, ThenBy, ThenBy... Tùy theo bên chuyên môn đưa ra thì nó vẫn ra kết quả đúng mà không cần dùng boosting hay function_score.
 
Thread hay :D Chấm hóng các cao nhân.

Theo tôi biết thì về mặt thực hành, người ta không làm như thế với sorting vì nó đủ nhanh và tiện lợi với những indexing có sẵn trên các field. Nhờ các indexing này mà giả sử mỗi query sử dụng sort ASC hay DSC on-the-fly đều tương đối nhanh.
Về việc bạn muốn "phẳng hóa" một câu query multi-sort thành 1 single sort. Nó sẽ rơi nhiều hơn vào thuật toán ranking, mà các thuật toán ranking này bạn sẽ phải tự phát triển phần nào chứ không có tích hợp sẵn thuật toán chuyển đổi từ multi-sort sang ranking score
Bác có docs hay ebook nào nói kỹ về cái này không? Cho em xin với. Em search nó toàn ra mấy cái chung chung.

@4nh7i3m bác coi thử xem có giúp được cho cái bác định làm không http://orion.lcg.ufrj.br/Dr.Dobbs/books/book5/chap14.htm :oops:
 
Sửa lần cuối:
về cơ bản luôn có các để convert các sort criteria về dạng số, và chỉ khó khi bạn k các criteria của b nhiều và khó đưa ra thuật toán compare. vd google index ranking.
vs dữ liệu b đwa ra, build ntn:
  • SortBy: Các sản phẩm có flag highlight (string) sẽ lên đầu -> score+ (max sort order + 10)
  • ThenBy vị trí các sản phẩm được xác định qua SortOrder (int) -> score + (5->max sort order)
  • ThenBy các sản phẩm có flag new (bool) -> score + 3
  • ThenBy các sản phẩm có flag available (bool), tức là còn trong kho -> score + 1

bỏ sort kiểu nào thì - số score tương ứng
 
Câu hỏi đặt ra là số lượng sản phẩm đã lên tới hàng tỷ sản phẩm chưa? => từ đó sẽ chọn loại DB phù hợp và nhanh nhất

Brainstorm là đưa ra nhiều ý tưởng khác nhau để tìm hiểu ưu khuyết từng ý tưởng và chọn cái phù hợp nhất, ở đây chỉ thấy bạn đưa ra đề bài và chọn solution dạng hash search conditions thành 1 số để tiện cho cách bạn code khi dùng ES (nếu ko muốn nói là lười)

Giả thiết số lượng sản phẩm dưới 1 tỷ cứ dùng relation db như mysql, postgres bình thường khá nhanh và nếu có nhiều request tới thì thêm tầng cache khoảng 5-10’ tuỳ biz thực tế
 
Ngoài ra, function_score thì phải giải quyết bài toán criteria với giá trị null hoặc boolean với giá trị false thế nào? Mà script thì quay trở lại như tui mô tả ở trên là có thuật toán nào để gom các criteria thành một Lòng/Integer hay không?

giả sử tất cả các sort criteria của bạn đều convert về query context, nếu thế thì trong query context mọi query đều có score. xài query expalain sẽ hiểu đc.
VD với trường hợp check null, bạn có thể tạo 1 query check field exits rồi trực tiếp boost nó với 1 số âm gọi là A để giảm score, hoặc nếu muốn dùng hàm nhân thì wrap query vào trong function và nhân score với 1 số thập phân gọi là B để giảm score. cái việc lựa chọn giá trị của A và B ở đây hoàn toàn phụ thuộc vào bạn và business, nó chính là quá trình trừu tượng hóa cả 1 hàm toán học tính score thành ES query. cái này quá specific, phụ thuộc vào business và ko có standard algorithm.
 

Thống kê chủ đề

Ngày tạo
4nh7i3m,
Người trả lời cuối
PrInc3oD,
Trả lời
23
Lượt xem
1.945
Quay lại
Lên đầu trang