75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
|
|
package db
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"regexp"
|
|||
|
|
"strings"
|
|||
|
|
"unicode"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
var punctuationReg = regexp.MustCompile(`[^\p{L}\p{N}]+`)
|
|||
|
|
|
|||
|
|
// BigramTokenize 将文本进行二元分词,用于全文检索影子列
|
|||
|
|
// 规则:
|
|||
|
|
// 1. 移除非字母数字的标点符号,按空格/标点初步切分块。
|
|||
|
|
// 2. 对每个块内的 CJK(中日韩)字符,使用滑动窗口进行 2-gram 切分。
|
|||
|
|
// 3. 对于块内的非 CJK(英文、数字等)字符,按单词整体保留。
|
|||
|
|
func BigramTokenize(text string) string {
|
|||
|
|
if text == "" {
|
|||
|
|
return ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 初步切分,按非字母数字字符分割
|
|||
|
|
chunks := punctuationReg.Split(text, -1)
|
|||
|
|
var allTokens []string
|
|||
|
|
|
|||
|
|
for _, chunk := range chunks {
|
|||
|
|
if chunk == "" {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
runes := []rune(chunk)
|
|||
|
|
length := len(runes)
|
|||
|
|
|
|||
|
|
var currentWord []rune
|
|||
|
|
for i := 0; i < length; i++ {
|
|||
|
|
r := runes[i]
|
|||
|
|
if isCJK(r) {
|
|||
|
|
// 遇到中文字符,先冲刷掉之前的英文单词
|
|||
|
|
if len(currentWord) > 0 {
|
|||
|
|
allTokens = append(allTokens, string(currentWord))
|
|||
|
|
currentWord = nil
|
|||
|
|
}
|
|||
|
|
// 1-gram
|
|||
|
|
allTokens = append(allTokens, string(r))
|
|||
|
|
// 2-gram
|
|||
|
|
if i < length-1 && isCJK(runes[i+1]) {
|
|||
|
|
allTokens = append(allTokens, string(runes[i:i+2]))
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
// 累积英文/数字
|
|||
|
|
currentWord = append(currentWord, r)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 循环结束,冲刷最后一个单词
|
|||
|
|
if len(currentWord) > 0 {
|
|||
|
|
allTokens = append(allTokens, string(currentWord))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 去重,减小索引体积
|
|||
|
|
tokenMap := make(map[string]bool)
|
|||
|
|
var uniqueTokens []string
|
|||
|
|
for _, t := range allTokens {
|
|||
|
|
if !tokenMap[t] {
|
|||
|
|
tokenMap[t] = true
|
|||
|
|
uniqueTokens = append(uniqueTokens, t)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return strings.Join(uniqueTokens, " ")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func isCJK(r rune) bool {
|
|||
|
|
return unicode.Is(unicode.Han, r) ||
|
|||
|
|
unicode.In(r, unicode.Hiragana, unicode.Katakana, unicode.Hangul)
|
|||
|
|
}
|