MySQL 전체 텍스트 검색 관련성을 조작하여 한 필드를 다른 필드보다 '가치 있는' 필드로 만들려면 어떻게 해야 합니까?
키워드와 내용이라는 두 개의 열이 있다고 가정합니다.두 가지 모두에 대한 전체 텍스트 색인을 가지고 있습니다.저는 키워드에 foo가 있는 행이 내용에 foo가 있는 행보다 관련성이 있었으면 합니다.MySQL이 키워드의 일치 항목을 내용의 일치 항목보다 더 높게 가중치를 부여하려면 어떻게 해야 합니까?
저는 "match against" 구문을 사용하고 있습니다.
솔루션:
다음과 같은 방법으로 이 작업을 수행할 수 있었습니다.
SELECT *,
CASE when Keywords like '%watermelon%' then 1 else 0 END as keywordmatch,
CASE when Content like '%watermelon%' then 1 else 0 END as contentmatch,
MATCH (Title, Keywords, Content) AGAINST ('watermelon') AS relevance
FROM about_data
WHERE MATCH(Title, Keywords, Content) AGAINST ('watermelon' IN BOOLEAN MODE)
HAVING relevance > 0
ORDER by keywordmatch desc, contentmatch desc, relevance desc
세 개의 전체 텍스트 색인 작성
- 키워드란에 하나
- 내용란에 하나
- 키워드와 콘텐츠 열 모두에 하나씩
그러면, 질문은 다음과 같습니다.
SELECT id, keyword, content,
MATCH (keyword) AGAINST ('watermelon') AS rel1,
MATCH (content) AGAINST ('watermelon') AS rel2
FROM table
WHERE MATCH (keyword,content) AGAINST ('watermelon')
ORDER BY (rel1*1.5)+(rel2) DESC
은 요은점입니다.rel1
에서 쿼리의 관련성을 제공합니다.keyword
열(해당 열에서만 인덱스를 생성했기 때문).rel2
동일하게 수행하지만,content
기둥. 이제 하여 이 두 할 수 있습니다.이제 원하는 가중치를 적용하여 이 두 가지 관련성 점수를 함께 추가할 수 있습니다.
그러나 이 두 인덱스 중 하나를 실제 검색에 사용하지 않습니다.이를 위해 두 열 모두에 있는 세 번째 인덱스를 사용합니다.
인덱스(키워드, 내용)는 리콜을 제어합니다.아, 반환되는 것.
두 개의 개별 인덱스(키워드에만 하나, 내용에만 하나)가 관련성을 제어합니다.여기에 자신만의 가중치 기준을 적용할 수 있습니다.
여러 인덱스를 사용할 수 있습니다(또는 쿼리 시 사용하는 인덱스와 가중치를 다른 요인에 따라 변경).쿼리에 중지 단어가 포함된 경우 키워드에서만 검색... 쿼리에 3개 이상의 단어가 포함된 경우 키워드에 대한 가중치 편향을 줄입니다.
각 인덱스는 디스크 공간을 사용하므로 인덱스가 많을수록 디스크가 늘어납니다.또한 mysql의 메모리 설치 공간도 증가합니다.또한 업데이트할 인덱스가 더 많기 때문에 삽입하는 데 시간이 더 오래 걸립니다.
귀사의 상황에 맞게 성능을 벤치마크해야 합니다(벤칭을 위해 mysql 쿼리 캐시를 끄면 결과가 왜곡됩니다).이것은 구글 등급의 효율적이지는 않지만, 꽤 쉽고 "즉시"이며 쿼리에서 "좋아요"를 사용하는 것보다 훨씬 더 좋습니다.
저는 그것이 정말 잘 작동한다고 생각합니다.
실제로 사례 문장을 사용하여 플래그 쌍을 만드는 것이 더 나은 해결책이 될 수 있습니다.
select
...
, case when keyword like '%' + @input + '%' then 1 else 0 end as keywordmatch
, case when content like '%' + @input + '%' then 1 else 0 end as contentmatch
-- or whatever check you use for the matching
from
...
and here the rest of your usual matching query
...
order by keywordmatch desc, contentmatch desc
이는 모든 키워드 일치가 모든 콘텐츠 전용 일치보다 높은 순위를 차지하는 경우에만 적용됩니다.키워드와 콘텐츠 모두 일치하는 것이 가장 높은 순위라는 가정도 했습니다.
두 개의 전체 텍스트 색인만 사용하는 간단한 버전(@mintywalker에서 가져온 자격 증명):
SELECT id,
MATCH (`content_ft`) AGAINST ('keyword*' IN BOOLEAN MODE) AS relevance1,
MATCH (`title_ft`) AGAINST ('keyword*' IN BOOLEAN MODE) AS relevance2
FROM search_table
HAVING (relevance1 + relevance2) > 0
ORDER BY (relevance1 * 1.5) + (relevance2) DESC
LIMIT 0, 1000;
이렇게 하면 두 개의 전체 인덱스 열이 모두 검색됩니다.keyword
일치하는 관련성을 두 개의 별도 열로 선택합니다.않는 하고 (를 다시 합니다.content_ft
전문 .복합 전체 텍스트 색인은 필요하지 않습니다.
부울 모드에서 MySQL은 ">" 및 "<" 연산자를 지원하여 행에 할당된 관련성 값에 대한 단어의 기여를 변경합니다.
저는 이런 것이 효과가 있을지 궁금합니다.
SELECT *,
MATCH (Keywords) AGAINST ('>watermelon' IN BOOLEAN MODE) AS relStrong,
MATCH (Title,Keywords,Content) AGAINST ('<watermelon' IN BOOLEAN MODE) AS relWeak
FROM about_data
WHERE MATCH(Title, Keywords, Content) AGAINST ('watermelon' IN BOOLEAN MODE)
ORDER by (relStrong+relWeak) desc
MySQL 전체 텍스트 검색에서는 지원되지 않는 것으로 알고 있지만 키워드 필드에서 해당 단어를 여러 번 반복하면 효과를 얻을 수 있습니다.키워드 "foo bar"를 사용하는 대신 "foo bar foo bar"를 사용하면 키워드 열에서 foo와 bar가 모두 동일하게 중요하며, 이러한 키워드가 여러 번 나타나기 때문에 mysql과 더 관련이 있습니다.
우리는 이것을 우리 사이트에서 사용하고 그것은 작동합니다.
그것은 당신이 정확히 무엇을 의미하느냐에 달려 있습니다.
저는 키워드에 foo가 있는 행이 내용에 foo가 있는 행보다 관련성이 있었으면 합니다.
키워드에 foo가 있는 행이 내용에 foo가 있는 행 앞에 와야 한다는 뜻이라면, 두 개의 별도 쿼리를 수행하겠습니다. 하나는 키워드에 대한 쿼리이고 다른 하나는 요청된 경우에만 해당됩니다.
저는 몇 년 전에 이것을 했지만, 전체 텍스트 색인 없이 했습니다.저는 코드를 손에 넣을 수는 없지만(전 고용주) 그 기술은 잘 기억하고 있습니다.
간단히 말해서, 저는 각 열에서 "무게"를 선택했습니다.예:
select table.id, keyword_relevance + content_relevance as relevance from table
left join
(select id, 1 as keyword_relevance from table_name where keyword match) a
on table.id = a.id
left join
(select id, 0.75 as content_relevance from table_name where content match) b
on table.id = b.id
여기에 있는 어떤 엉터리 SQL도 용서해 주세요. 몇 년 전에 작성해야 했던 것 같은데, 저는 이것을 즉흥적으로 하고 있습니다.
이것이 도움이 되길 바랍니다!
제이제이
저는 비슷한 것이 필요했고 OP의 솔루션을 사용했는데, 전체 텍스트가 부분 단어와 일치하지 않는다는 것을 알게 되었습니다.따라서 '수박'이 단어의 일부로 키워드 또는 내용에 있으면(수박 판매 관리자처럼) 일치하지 않고 WHERE MATCH로 인해 결과에 포함되지 않습니다.그래서 저는 장난을 치고 OP의 질문을 다음과 같이 수정했습니다.
SELECT *,
CASE WHEN Keywords LIKE '%watermelon%' THEN 1 ELSE 0 END AS keywordmatch,
CASE WHEN Content LIKE '%watermelon%' THEN 1 ELSE 0 END AS contentmatch,
MATCH (Title, Keywords, Content) AGAINST ('watermelon') AS relevance
FROM about_data
WHERE (Keywords LIKE '%watermelon%' OR
Title LIKE '%watermelon%' OR
MATCH(Title, Keywords, Content) AGAINST ('watermelon' IN BOOLEAN MODE))
HAVING (keywordmatch > 0 OR contentmatch > 0 OR relevance > 0)
ORDER BY keywordmatch DESC, contentmatch DESC, relevance DESC
이게 도움이 되길 바랍니다.
모든 키워드 일치가 모든 내용 일치보다 "값이 더 크다"는 메트릭인 경우 행 수가 있는 조합을 사용할 수 있습니다.이 선들을 따라 뭔가.
select *
from (
select row_number() over(order by blahblah) as row, t.*
from thetable t
where keyword match
union
select row_number() over(order by blahblah) + @@rowcount + 1 as row, t.*
from thetable t
where content match
)
order by row
그것보다 더 복잡한 것은, 당신이 모든 행에 실제 무게를 적용하고 싶은 경우, 저는 어떻게 도와야 할지 모르겠습니다.
언급URL : https://stackoverflow.com/questions/547542/how-can-i-manipulate-mysql-fulltext-search-relevance-to-make-one-field-more-val
'programing' 카테고리의 다른 글
Sass - 배경 불투명도를 위해 16진수를 RGBa로 변환 (0) | 2023.08.01 |
---|---|
여러 비동기 파이프 변수가 있는 *ngIf (0) | 2023.08.01 |
MySQLi 개수(*)는 항상 1을 반환합니다. (0) | 2023.08.01 |
폰트 어썸의 코그 아이콘 색상을 변경할 수 있습니까? (0) | 2023.08.01 |
스크롤 위치 추적 및 다른 구성 요소에 알림 (0) | 2023.08.01 |