如何匹配查询中包含一个或多个单词的行,但没有任何不在查询中的单词?

How to match rows with one or more words in query, but without any words not in query?

我在 MySQL 数据库中有一个 table,其中有一个逗号分隔的标签列表。

我希望用户能够输入逗号分隔的标签列表,然后使用 Sphinx 或 MySQL 到 select 行,其中至少有一个 查询中的标记,但查询中没有任何标记

查询可以包含不在行中的其他标签,但如果行中包含不在查询中的标签,则不应匹配这些行。

我想使用 Sphinx 或 MySQL 进行搜索。

这是一个例子:

creatures:
----------------------------
| name |  tags             |
----------------------------
| cat  | wily,hairy        |
| dog  | cute,hairy        |
| fly  | ugly              |
| bear | grumpy,hungry     |
----------------------------

示例搜索:

wily,hairy         <-- should match cat
cute,hairy,happy   <-- should match dog
happy,cute         <-- no match (dog has hairy)
ugly,yuck,gross    <-- should match fly
hairy              <-- no match (dog has cute cat has wily)
grumpy             <-- no match (bear has hungry)
grumpy,hungry      <-- should match bear
wily,grumpy,hungry <-- should match bear

是否可以用 Sphinx 或 MySQL 做到这一点?

重申一下,查询将是一个逗号分隔的标签和行的列表,这些标签和行具有 至少一个输入的标签 没有任何标签查询没有 应该 selected。

Sphinx 表达式排序器应该可以做到这一点。

sphinxQL> SELECT *, WEIGHT() AS w FROM index 
   WHERE MATCH('@tags "cute hairy happy"/1') AND w > 0 
   OPTION ranker=expr('IF(word_count>=tags_len,1,0)');

基本上你希望匹配标签的数量永远不会少于标签的数量。

注意这些只是给所有文档的权重为 1,如果想获得更精细的排名(例如匹配其他关键字),它会变得更加复杂。

您需要在索引上启用 index_field_lengths 才能获得 tags_len 属性。

(相同的概念在 mysql 中显然是可能的。可能使用 FIND_IN_SET 进行匹配。或者使用第二列来存储数字,或者计算标签的数量,使用 say REPLACE 函数)


编辑添加,关于多个字段的详细信息...

sphinxQL> SELECT *, WEIGHT() AS w FROM index 
   WHERE MATCH('@tags "cute hairy happy"/1 @tags2 "one two thee"/1') AND w = 2 
   OPTION ranker=expr('SUM(IF(word_count>=IF(user_weight=2,tags2_len,tags_len),1,0))'), 
    field_weights=(tags=1,tags2=2);

SUM函数对每个字段依次运行,所以需要使用user_weight系统才能区分当前枚举的是哪个字段。