2009-10-16 49 views
1

有人可以建议的想法,如何将用户输入(少量字)匹配到系统中适当的标签(每个标签也是1或N个字)?用户搜索关键字与标签的匹配

这里是示例来演示问题: 我有一个标签,分配给对象。例如(标签昏迷分开的,但在现实生活中,我有关系表)

Object     Tags 
Earth     World, reality 
World of warcraft 3  World Of warcraft, virtual reality 
quake     game, virtual 

我想获得如下:

用户输入“世界‘:结果是’地球 '

用户输入' 魔兽世界的 ':结果是' 魔兽世界3'的

这很简单,精确搜索。但是:

用户输入 '游戏世界 ':结果应该是由两个标签 - ' 地球', '地震'

用户输入 '虚拟现实':返回所有3个记录

用户输入 '现实虚拟':地球,地震

我正在使用t-sql进行搜索,全文搜索已启用并用于在主文本中查找关键字。 C#是中间层。但我更喜欢在t-sql级别上有解决方案。

更新1 首先我所要做的,是不允许空格标签,像计算器。任何其他想法都会被提升。

回答

0

将这种复杂的业务逻辑放入SQL代码中并不是一个好主意!把它放在中间层,如果你担心性能使用一些缓存机制。

+0

好点。不过,我担心在C#级别将所有关键字组合与标签匹配的速度会变慢。 – st78 2009-10-16 08:47:15

+0

情况正好相反。除非您拥有大量关键字(> 100MB),否则不需要全文索引。你总是可以用嵌套的hashtables/dictionnaries来实现c#索引。 – Manu 2009-10-16 08:59:25

+0

虽然,除非你的数据库(这是唯一的),你实际上可以有多个使用C#代码的服务器......这里有自然的平行性! – 2009-10-16 09:02:43

1

你需要的分裂功能在搜索字符串分割标记,然后尝试在标签

FUNCTION [dbo].[SplitString] 
(
     @String VARCHAR(8000) , 
     @Delimiter VARCHAR(10) 
) 
RETURNS @RetTable TABLE(
     String varchar(1000) 
) 
AS 
BEGIN 
    DECLARE @i INT , 
      @j INT 
    SELECT @i = 1 
    WHILE @i <= LEN(@String) 
    BEGIN 
     SELECT @j = CHARINDEX(@Delimiter, @String, @i + 1) 
     IF @j = 0 
     BEGIN 
      SELECT @j = LEN(@String) + 1 
     END 
     INSERT @RetTable SELECT LTRIM(RTRIM(SUBSTRING(@String, @i, @j - @i))) 
     SELECT @i = @j + LEN(@Delimiter) 
    END 
    RETURN 
END 


DECLARE @String VARCHAR(8000) , 
     @Delimiter VARCHAR(10) 
DECLARE @RetTable TABLE(
     String varchar(1000) 
) 

SELECT @String = 'world of ', 
     @Delimiter = ' ' 

--split FUNCTION that returns a table of tags to match 
    DECLARE @i INT , 
      @j INT 
    SELECT @i = 1 
    WHILE @i <= LEN(@String) 
    BEGIN 
     PRINT @i 
     SELECT @j = CHARINDEX(@Delimiter, @String, @i + 1) 
     IF @j = 0 
     BEGIN 
      SELECT @j = LEN(@String) + 1 
     END 
     INSERT @RetTable SELECT LTRIM(RTRIM(SUBSTRING(@String, @i, @j - @i))) 

     SELECT @i = @j + LEN(@Delimiter) 
    END 

SELECT * FROM @RetTable 
--split FUNCTION that returns a table of tags to match 

DECLARE @Table TABLE(
     Objects VARCHAR(MAX), 
     Tags VARCHAR(MAX) 
) 

INSERT INTO @Table (Objects,Tags) SELECT 'Earth', 'World,reality' 
INSERT INTO @Table (Objects,Tags) SELECT 'World of warcraft 3', 'World Of warcraft,virtual,reality' 
INSERT INTO @Table (Objects,Tags) SELECT 'quake', 'game,virtual' 


SELECT DISTINCT 
     t.* 
FROM @Table t, 
     @RetTable r 
WHERE Tags LIKE '%' + String + '%,%' 
OR  Tags LIKE '%,%' + String + '%,%' 
OR  Tags LIKE '%,%' + String + '%' 

类似的东西进行匹配。

3

您可能需要使用Velocity缓存引擎进行调查,因为它有用于标记(GetObjectsByTagGetObjectsByAllTagsGetObjectsByAnyTag)和所有的辛勤工作已经为你做了相当丰富的支持!你所要做的就是用适当的标签将你的对象加载到缓存中。

+0

感谢您的链接,我不知道它。我一定会检查它。 但是,这仅仅是我的搜索问题的一部分,我很少有机会使用第三方。 – st78 2009-10-16 09:57:25

+1

取决于你如何解释第三方。如果你已经在使用C#,那么它只是微软的另一个组件。 – PhilPursglove 2009-10-16 10:21:38