搜索单词结构的最佳方法是什么?

时间:2013-11-06 19:00:07

标签: php mysql full-text-search tagging

我想建立一个大约有400个字符串的数据库。我想让数据库可搜索。

数据库的结构如下:

Brand | model |additional products | price | search words | (this is 1 string, there will about 400 strings)

每个字符串上将有2到50个搜索词。通过单击复选框完成搜索,将在数据库中搜索标记的复选框单词。

我的问题是如何将所有搜索词编入索引的最佳方法? 我正在考虑两种方式:

  1. search words字段中,所有可搜索的字词都会显示为:1GB RAM, 512GB RAM, ATA, SATA…,依此类推每个字符串。这意味着所有单词将在由“,”分隔的特定字符串中以相同的原始单词。

  2. 每个搜索词都有自己的行,如:| search words 1| search words 2| search words 3 | search 4 words 5|… ..等等。在|search words 1|1GB RAM这个词就是。 | search words 2| 512GB RAM中的单词{{1}}将依此类推......这意味着在字符串中可能有一半的搜索字行会被搜索字填充。

  3. 在选项2中,数据库中将有超过50行,并且不同列中的所有搜索词(每个产品的每列中有1个)。在选项1中,将有1行,每个产品的同一列中包含所有单词。

    或者有更好的方法吗?

3 个答案:

答案 0 :(得分:4)

即使接受了另一个答案......我更多地解释了这个想法,因为我觉得它符合“最佳实践”,并允许您将多个单词与一个项目关联,而不重复数据。

你最终应该有三张桌子:

item:        item_id | Brand | model |additional products | price 

word:        word_id | word 

item_word:   item_word_id | item_id | word_id 

数据看起来像:

项目:

item_id   brand     model        additional_products   price 
1         nokia     g5                                   100 
2         toshiba   satellite                           1000 

字:

word_id   word 
1         1 GB
2         ATA
3         SATA
4         512BG RAM 

item_word:

item_word_id    itwm_id     word_id
1               1           1
2               1           2
3               2           3
4               2           4

以便nokia有这些词:1 GB, ATAtoshiba有这些词:SATA, 512BG RAM。 (我意识到这没有多大意义,这只是一个例子)


然后查询它......

select  item.*, word 

from    item 

        join item_word on item.item_id = item_word.item_id

        join word on item_word.word_id = word.word_id 

并将其过滤为......

select  item.*, word 

from    item 

        join item_word on item.item_id = item_word.item_id

        join word on item_word.word_id = word.word_id 

 where  word in ('1GB RAM', '512GB RAM', 'ATA')

看看你甚至可以尝试的最相关的结果是什么......

select  item.item_id, item.brand, item.model, count(*) as word_count

from    item 

        join item_word on item.item_id = item_word.item_id

        join word on item_word.word_id = word.word_id 

 where  word in ('1GB RAM', '512GB RAM', 'ATA')

 group  by item.item_id, item.brand, item.model

 order  by count(*) desc 

对于与所提供的所有单词匹配的内容,您将使用...

select  item.item_id, item.brand, item.model, count(*) as word_count

from    item 

        join item_word on item.item_id = item_word.item_id

        join word on item_word.word_id = word.word_id 

 where  word in ('1GB RAM', 'ATA')

 group  by item.item_id, item.brand, item.model

 having count(*)=2

其中3是in声明中的字数... word in ('1GB RAM', 'ATA')。在这种情况下,它是2


如果你只是......

item:  Brand | model |additional products | price | long_word_string

然后你必须做...

 select  * 
 from    item 
 where   long_word_string like '1GB RAM' or word like 'ATA'

甚至......

 select  * 
 from    item 
 where   long_word_string regexp '1GB RAM|ATA'

但是那些效率非常低/昂贵的方法......而且最好只是规范化事情,这样你就不会存储额外的数据并且会在尝试解决问题时扼杀性能

这有意义吗?它能回答你的问题吗?

编辑:我的答案输给了两张桌子......我现在关注的是OP的数据库。

答案 1 :(得分:2)

将您的搜索字词存储在永无止境的其他列中与数据库“规范化”相反。将所有内容存储在一列中通常是最后一个选项,因为如果您使用多列,则更容易细分搜索字词。

创建一个单独的表并将原始表连接到此表。你的结构看起来像这样:

原始表

enter image description here

新表

enter image description here

我在原始表中添加了一个主键列。这将使JOIN更容易。使用以下语句连接两个表:

SELECT original_table.*
FROM original_table AS ABB2
    JOIN new_table AS ABB1 ON ABB1.product_id = ABB2.id
WHERE search_word = "your search term"

新表格中的“search_word”列是与原始表格中的每个条目相关联的字词。

如果您希望启用模糊(返回包含搜索词的所有结果)搜索,则可以将“%”通配符添加到WHERE语句中。

答案 2 :(得分:0)

感谢所有建议。 IT非常有帮助。我想我会尝试去分离关键词的表格,但我不知道如何编写这部分代码,所以也要开始学习它:)