I have a table with the following contents:
- CategoryID
- ParentID
- Name
I would like to have a search functionality that would search the whole hierarchy, for exmple this is the breadcrumb of a category:
Motorcycles/Japan/Kawasaki/600cc to 800cc/1998-2004
If someone searches for "600cc Kawasaki" I would like the above category to be returned. So the categorypath which has the most matches should return.
At the moment I came up with this:
IF ISNULL(@searchTerm, '') = ''
SET @searchTerm = '""'
DECLARE @Result TABLE (CategoryId int)
DECLARE CategoryCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT CategoryId, ParentId, Name
FROM Category
WHERE FREETEXT([Name], @searchTerm)
OPEN CategoryCursor
DECLARE @CategoryId int
DECLARE @ParentId int
DECLARE @Name nvarchar(100)
FETCH NEXT FROM CategoryCursor INTO @CategoryId, @ParentId, @Name
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @FullPath nvarchar(1000)
SET @FullPath = @Name
WHILE @ParentId <> 0
BEGIN
SELECT @ParentId = ParentId, @Name = [Name]
FROM Category
WHERE CategoryId = @ParentId
SET @FullPath = @Name + '\' + @FullPath
END
-- Check if @FullPath contains all of the searchterms
DECLARE @found bit
DECLARE @searchWords NVARCHAR(100)
DECLARE @searchText NVARCHAR(255)
DECLARE @pos int
SET @found = 1
SET @searchWords = @searchTerm + ' '
SET @pos = CHARINDEX(' ', @searchWords)
WHILE @pos <> 0
BEGIN
SET @searchText = LEFT(@searchWords, @pos - 1)
SET @searchWords = STUFF(@searchWords, 1, @pos, '')
SET @pos = CHARINDEX(' ', @searchWords)
IF @searchText = '' CONTINUE
IF @FullPath NOT LIKE '%' + @searchText + '%'
BEGIN
SET @found = 0
BREAK
END
END
IF @found = 1
INSERT INTO @Result VALUES(@CategoryId)
FETCH NEXT FROM CategoryCursor INTO @CategoryId, @ParentId, @Name
END
CLOSE CategoryCursor
DEALLOCATE CategoryCursor
SELECT *
FROM Category
WHERE categoryID IN (SELECT categoryId FROM @Result)
This will first find all catagorynames which contain any of the searchwords. Problem is, I don't want "600cc" for other brands to return, only the one which is related to "Kawasaki". So next I build the breadcrumb for the current category and see if it contains all of the searchwords.
It works but I think it is ineffective so i'm looking for a better method.
Perhaps storing the complete path as text in a new column and search on that?