Lucene语法介绍
Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引和查询索引,以及部分文本分析的引擎,Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎,Lucene在全文检索领域是一个经典的祖先,现在很多检索引擎都是在其基础上创建的,思想是相通的。
需求
项目采用简易Lucene语法,会使用AND、NOT、OR、(、)
前端需要解析字符串,并把AND、NOT中的词提取出来对项目中的词进项高亮
难点
需要排除NOT后到下一个AND、OR、)的词,NOT后的值会出现很多种,括号可以嵌套很多层
例子:
'黑龙江 OR TT NOT 删除 OR 我爱你 AND 火龙果 AND NOT (删除 OR 删除 (删除 OR 删除)) AND NOT (删除 OR 删除) OR (TT NOT (删除 AND 删除) OR 好吧) OR ((我不知道 OR 好的) AND NOT (删除 AND 删除) AND NOT (删除 AND 删除)) AND NOT 删除 AND NOT 删除 AND(Vue NOT 删除) OR JS AND (龙 AND NOT (删除 OR 删除) AND java) AND (456 AND (789 ADN 567 OR (vue NOT (删除 OR 删除))))'
// 需要把删除去除掉 也就是 NOT后的值
逻辑思路及步骤在代码注释中
代码如下
// 例子 let Text = '黑龙江 OR TT NOT 删除 OR 我爱你 OR 黑河 OR AI AND 火龙果 AND NOT (删除 OR 删除 (删除 OR 删除)) AND NOT (删除 OR 删除) OR (TT NOT (删除 AND 删除) OR 好吧) OR ((我不知道 OR 好的) AND NOT (删除 AND 删除) AND NOT (删除 AND 删除)) AND NOT 删除 AND NOT 删除'
// 要求 把OR、AND中的词提取出来并排除NOT中的内容
// 第一步 为了防止用户输入中文‘(’、‘)’ 我们把所有中文‘(’、‘)’转换成英文‘(’、‘)’
// 第二步 我们先通过' NOT '进行拆分
// -------------------------------------
// 第三步 这里NOT后会出现两种情况 我们判断' NOT '右侧是'(' 还是没有'('
// 情况1、右侧出现时'('
// 出现'('的 我们计算'('数量 通过'('的数量我们去向右边取同样数量的 ')' 然后把第一个'(' 和 最后一个 ')' 的内容直接排除 并把排除的内容保存
// 情况2、右侧没有'('
// 没有出现的 我们直接把右侧第直到下一个' '之间的内容全部删除
// 然后去除'(' ')' AND OR 转换成数组
// --------------------------------------
// 最后 拿删除的内容与保存的内容对比并删除保存的内容中出现删除的内容的词
function luncene(Text) {
//所有中文括号转换英文括号
const LeftC = '('
const LeftCRegExp = new RegExp(LeftC, 'g')
const LeftCNew = '('
Text = Text.replace(LeftCRegExp,LeftCNew)
const RightC = ')'
const RightCRegExp = new RegExp(RightC, 'g')
const RightCNew = ')'
Text = Text.replace(RightCRegExp,RightCNew)
// 保留删除的词
let notArray = []
const arr = Text.split(' NOT ')
// 先通过NOT拆分 数组第一个全部保留,其余需要处理
arr.forEach((val, i) => {
if (i != 0) {
// 如果第一个字符串为左括号则处理数据
if (val[0] == '(') {
let leftCount = 0 // 左括号出现的次数
let RightCount = 0 // 右括号出现的次数
let leftIndex = val.indexOf('(') // 左括号索引
let rightIndex = val.indexOf(')') // 右括号索引
while (leftIndex != -1 && leftIndex < rightIndex) {
// console.log(leftIndex, rightIndex)
leftCount++
leftIndex = val.indexOf('(', leftIndex + 1)
}
while (rightIndex != -1) {
// console.log(leftIndex, rightIndex)
RightCount++
// 查找左括号闭合索引
if (leftCount == RightCount) {
// console.log('闭合索引', rightIndex)
arr[i] = val.substr(rightIndex + 1, val.length)
let NotItem = val.split('(').join('').split(')').join('').split('AND').join('').split('OR').join('')
NotItem.split(' ').forEach(item => {
if (item) {
// 保留删除的词
notArray.push(item)
}
})
}
rightIndex = val.indexOf(')', rightIndex + 1)
}
} else {
// 没有括号则去除第一个数据
val.split(' ').forEach(res=>{
if(res)
{
notArray.push(res)
}
})
arr[i] = val.split(' ').splice(1).join(' ')
}
}
})
let newArr = []
arr.forEach((val, i) => {
// 最终数据处理 去除括号 and or
arr[i] = val.split('(').join('').split(')').join('').split('AND').join('').split('OR').join('')
// 去除空数据
arr[i].split(' ').forEach(item => {
if (item) {
newArr.push(item)
}
})
})
// 删除词与保留词进行对比
notArray.forEach(res=>{
newArr.forEach((ret,array)=>{
if(res===ret)
{
newArr.splice(array,1)
}
})
})
// 去重
return Array.from(new Set(newArr))
}
export{
luncene
}