簡體   English   中英

使用 Postgres 進行加權 + 有序標簽搜索

[英]Weighted + ordered tag search using Postgres

在對數萬個音頻文件進行 AI 文件分析后,我最終在 Postgres 數據庫中得到了這種數據結構:

id | name          | tag_1 | tag_2   | tag_3 | tag_4          | tag_5
1  | first song    | rock  | pop     | 80s   | female singer  | classic rock
2  | second song   | pop   | rock    | jazz  | electronic     | new wave
3  | third song    | rock  | funk    | rnb   | 80s            | rnb

標簽位置非常重要:越“靠左”,它在歌曲中就越突出。 標簽的數量也是有限的(50 個標簽),AI 總是為每首歌曲返回其中的 5 個標簽,沒有預期的 null 個值。

另一方面,這是我必須查詢的:

{"rock" => 15, "pop" => 10, "soul" => 3}

鍵是標簽名稱,值是任意權重。 條目數可以是 1 到 50 之間的隨機數。根據示例數據集,在這種情況下它應該返回 [1, 3, 2]

如果使用原始連接字符串可以更容易地實現,我也願意進行數據重組,但是......使用 Postgres(tsvectors?)是否可行,或者我真的必須為此使用 Elasticsearch 之類的東西嗎?

經過大量的試驗和錯誤,這就是我最終得到的結果,只使用 Postgres:

  1. 將所有數據集轉為整數,因此它會變成這樣(我還添加了列以更接近地匹配真實數據集):
id | bpm | tag_1 | tag_2 | tag_3 | tag_4 | tag_5
1  | 114 | 1     | 2     | 3     | 4     | 5
2  | 102 | 2     | 1     | 6     | 7     | 8
3  | 110 | 1     | 9     | 10    | 3     | 12
  1. 將請求作為字符串存儲在數組中(請注意,我之前使用某種“請求生成器”對這些請求進行了清理):
requests = [
  "bpm BETWEEN 110 AND 124 
   AND tag_1 = 1 
   AND tag_2 = 2
   AND tag_3 = 3
   AND tag_4 = 4
   AND tag_5 = 5",
  "bpm BETWEEN 110 AND 124 
   AND tag_1 = 1 
   AND tag_2 = 2
   AND tag_3 = 3
   AND tag_4 = 4
   AND tag_5 IN (1, 3, 5)",
  "bpm BETWEEN 110 AND 124 
   AND tag_1 = 1 
   AND tag_2 = 2
   AND tag_3 = 3
   AND tag_4 IN (1, 3, 5),
   AND tag_5 IN (1, 3, 5)",
   ....
]
  1. 簡單地循環請求數組,從最精確到最近似:
# Ruby / ActiveRecord example

track_ids = [] 
requests.each do |request|
  track_ids += Track.where([
                 "(#{request}) 
                 AND tracks.id NOT IN ?", track_ids
               ]).pluck(:id)

  break if track_ids.length > 200
end

... 完成了,我所有的歌曲都按相似度排序,最接近的匹配在頂部,更多的在底部。 他們得到的越近似,因為一切都是關於整數的,所以它非常快(在 100K 行數據集上足夠快)。 output 看起來像純粹的魔法:加分。 它仍然很容易被整個團隊調整和維護。

我知道這很粗糙,所以我願意接受任何更有效的方法來做同樣的事情,即使堆棧中需要其他東西(ES?),但到目前為止:這是一個簡單的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM