【问题标题】:Order full text search by exact match THEN prefixed matches按完全匹配排序全文搜索 THEN 前缀匹配
【发布时间】:2016-09-26 19:58:24
【问题描述】:

如何确保我的全文搜索结果按完全匹配和 THEN 前缀匹配排序?

SELECT ticker, name, ts_rank(document, to_tsquery('english', 'MAT:*')) AS rank
FROM (
  SELECT *, setweight(to_tsvector('english', ticker), 'A') || setweight(to_tsvector('english', name), 'B') AS document
  FROM ( VALUES
     ('MATI-R' , 'MATICHON PCL.NVDR')
    ,('MATCH-R', 'MATCHING MAXIMIZE SLN. NVDR')
    ,('MATV'   , 'MATAV-CABLE SYS.MEDIA SPN.ADR 1:2 DEAD - DELIST.03/07/06')
    ,('MAT'    , 'MATISSE HOLDINGS DEAD - 03/10/06')
    ,('MAT'    , 'MATTEL')
  ) data (ticker,name)
) ss ORDER BY rank DESC

我在https://www.postgresql.org/docs/9.5/static/datatype-textsearch.html 上尝试了一些建议,例如to_tsquery('english', 'MAT:A & MAT:*B'),但似乎没有一个能满足我的需求。当前输出为

 ticker  |                           name                           |   rank   
---------+----------------------------------------------------------+----------
 MATI-R  | MATICHON PCL.NVDR                                        |  1.45903
 MATCH-R | MATCHING MAXIMIZE SLN. NVDR                              |  1.27665
 MATV    | MATAV-CABLE SYS.MEDIA SPN.ADR 1:2 DEAD - DELIST.03/07/06 |  1.09427
 MAT     | MATISSE HOLDINGS DEAD - 03/10/06                         | 0.851098
 MAT     | MATTEL                                                   | 0.851098

当我想要更多类似的东西时

 ticker  |                           name                           |   rank
---------+----------------------------------------------------------+----------
 MAT     | MATTEL                                                   | ??
 MAT     | MATISSE HOLDINGS DEAD - 03/10/06                         | ??
 MATCH-R | MATCHING MAXIMIZE SLN. NVDR                              | ??
 MATI-R  | MATICHON PCL.NVDR                                        | ??
 MATV    | MATAV-CABLE SYS.MEDIA SPN.ADR 1:2 DEAD - DELIST.03/07/06 | ??

【问题讨论】:

    标签: postgresql full-text-search


    【解决方案1】:

    使用LIKEILIKE

    SELECT ticker, name, ts_rank(document, to_tsquery('english', 'MAT:*')) AS rank
    FROM (
      SELECT *, setweight(to_tsvector('english', ticker), 'A') || setweight(to_tsvector('english', name), 'B') AS document
      FROM ( VALUES
         ('MATI-R' , 'MATICHON PCL.NVDR')
        ,('MATCH-R', 'MATCHING MAXIMIZE SLN. NVDR')
        ,('MATV'   , 'MATAV-CABLE SYS.MEDIA SPN.ADR 1:2 DEAD - DELIST.03/07/06')
        ,('MAT'    , 'MATISSE HOLDINGS DEAD - 03/10/06')
        ,('MAT'    , 'MATTEL')
      ) data (ticker,name)
    ) ss ORDER BY name LIKE concat('%', ticker, '%') desc, rank DESC
    
     ticker  |                           name                           |   rank   
    ---------+----------------------------------------------------------+----------
     MAT     | MATISSE HOLDINGS DEAD - 03/10/06                         | 0.851098
     MAT     | MATTEL                                                   | 0.851098
     MATI-R  | MATICHON PCL.NVDR                                        |  1.45903
     MATCH-R | MATCHING MAXIMIZE SLN. NVDR                              |  1.27665
     MATV    | MATAV-CABLE SYS.MEDIA SPN.ADR 1:2 DEAD - DELIST.03/07/06 |  1.09427
    (5 rows)    
    

    【讨论】:

    • 这很有趣。如果我们对ticker 而不是name 进行排序,似乎它可以工作,但它也似乎有点hacky,因为它跳过了postgresql 全文搜索的排名能力。看起来使用全文搜索排名在更大的数据集上会更有性能。你有什么理由推荐这种方法而不是使用全文搜索机制的方法?
    • 首先,您无法通过全文搜索找到这样的完全匹配。使用like 不是代替全文搜索,而是在它旁边。这两个功能可以很好地协同工作。当然,like 在大型数据集上会更昂贵,但我看不到实现您想要的替代方案。
    • 有道理。我们现在正在使用一些归一化权重,并看到了相当不错的结果,但我认为我们最终会得到您的解决方案和这些解决方案的某种组合。
    猜你喜欢
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2020-04-18
    相关资源
    最近更新 更多