如果字符串中包含“-”(例如“3da549f0-0e88-4297-b6af-5179b74bd929”),如何进行全文搜索?
How to do a fulltext search if the string has '-' in it for e.g "3da549f0-0e88-4297-b6af-5179b74bd929"?
当我为该字段编制索引并搜索其中包含“-”的字符串(如上例)时,Arango 将其视为否定运算符,因此不会搜索该字符串。搜索这些包含'-'的文档的解决方案是什么?
编辑:
我刚去看了the source code。从那里看起来'-'只有在它是字符串中的第一个字符时才应该是一个问题。而且它不是您上面给出的示例中的第一个字符,所以我很困惑。
看起来没有任何方法可以转义“-”字符。另一个想法可能是在“-”前加上“+”。你试过了吗:
collection.fulltext(attribute, "3da549f0+-0e88+-4297+-b6af+-5179b74bd929");
我从阅读 the docs 中猜测,使用 "prefix:" 或 "complete:" 作为转义可能有效。
collection.fulltext(attribute, "complete:3da549f0-0e88-4297-b6af-5179b74bd929");
但显然不是。
正在尝试重现您所做的。如果您提供一个更好的可重现示例(仅限 arangosh),我的回答可能会更准确:
http+tcp://127.0.0.1:8529@_system> db._create("testIndex")
http+tcp://127.0.0.1:8529@_system> db.testIndex.ensureIndex({type: "fulltext", fields: ["complete:3da549f0-0e88-4297-b6af-5179b74bd929"]})
{
"fields" : [
"complete:3da549f0-0e88-4297-b6af-5179b74bd929"
],
"id" : "testIndex/4687162",
"minLength" : 2,
"sparse" : true,
"type" : "fulltext",
"unique" : false,
"isNewlyCreated" : true,
"code" : 201
}
http+tcp://127.0.0.1:8529@_system> db.testIndex.save({'complete:3da549f0-0e88-4297-b6af-5179b74bd929': "find me"})
{
"_id" : "testIndex/4687201",
"_key" : "4687201",
"_rev" : "4687201"
}
http+tcp://127.0.0.1:8529@_system> db._query('FOR doc IN FULLTEXT(testIndex, "complete:3da549f0-0e88-4297-b6af-5179b74bd929", "find") RETURN doc')
[object ArangoQueryCursor, count: 1, hasMore: false]
[
{
"_id" : "testIndex/4687201",
"_key" : "4687201",
"_rev" : "4687201",
"complete:3da549f0-0e88-4297-b6af-5179b74bd929" : "find me"
}
]
因此用例看起来不同:
db.test2.save({id: 'complete:3da549f0-0e88-4297-b6af-5179b74bd929'})
db.test2.ensureIndex({type: "fulltext", fields: ["id"]})
db._query('FOR doc IN FULLTEXT(test2, "id", "3da549f0-0e88-4297-b6af-5179b74bd929") RETURN doc')
这将 return 一个空结果。
要了解发生了什么,需要了解全文索引的工作原理。它在 word boundaries 处拆分文本并将其存储为一个列表,其中包含对索引中文档的引用。该索引全局词表中的一个词可能会引用多个文档。
查询索引后,将在索引全局词表中搜索请求的词,找到的每个词将包含包含该词的文档列表。这些桶被合并,returned 作为要迭代的文档的总列表。
了解the tokenizer a little better, I've added a tiny js wrapper that invokes it。
让我们看看它对您的字符串做了什么:
SYS_SPLIT_WORDS_ICU("ab cd", 0)
[
"ab",
" ",
"cd"
]
SYS_SPLIT_WORDS_ICU("3da549f0-0e88-4297-b6af-5179b74bd929", 0)
[
"3da549f0",
"-",
"0e88",
"-",
"4297",
"-",
"b6af",
"-",
"5179b74bd929"
]
所以你看,减号被视为单词边界,你的字符串被分区了。你现在有几个机会来规避这个:
- 删除插入的缺点
- 拆分搜索字符串,并使用散列中最有意义的部分,然后是实际值的 FILTER 语句
- 不要为此使用全文索引,而是使用跳过列表或哈希索引;它们的维护成本更低,可用于 FILTER 语句
当我为该字段编制索引并搜索其中包含“-”的字符串(如上例)时,Arango 将其视为否定运算符,因此不会搜索该字符串。搜索这些包含'-'的文档的解决方案是什么?
编辑: 我刚去看了the source code。从那里看起来'-'只有在它是字符串中的第一个字符时才应该是一个问题。而且它不是您上面给出的示例中的第一个字符,所以我很困惑。
看起来没有任何方法可以转义“-”字符。另一个想法可能是在“-”前加上“+”。你试过了吗:
collection.fulltext(attribute, "3da549f0+-0e88+-4297+-b6af+-5179b74bd929");
我从阅读 the docs 中猜测,使用 "prefix:" 或 "complete:" 作为转义可能有效。
collection.fulltext(attribute, "complete:3da549f0-0e88-4297-b6af-5179b74bd929");
但显然不是。
正在尝试重现您所做的。如果您提供一个更好的可重现示例(仅限 arangosh),我的回答可能会更准确:
http+tcp://127.0.0.1:8529@_system> db._create("testIndex")
http+tcp://127.0.0.1:8529@_system> db.testIndex.ensureIndex({type: "fulltext", fields: ["complete:3da549f0-0e88-4297-b6af-5179b74bd929"]})
{
"fields" : [
"complete:3da549f0-0e88-4297-b6af-5179b74bd929"
],
"id" : "testIndex/4687162",
"minLength" : 2,
"sparse" : true,
"type" : "fulltext",
"unique" : false,
"isNewlyCreated" : true,
"code" : 201
}
http+tcp://127.0.0.1:8529@_system> db.testIndex.save({'complete:3da549f0-0e88-4297-b6af-5179b74bd929': "find me"})
{
"_id" : "testIndex/4687201",
"_key" : "4687201",
"_rev" : "4687201"
}
http+tcp://127.0.0.1:8529@_system> db._query('FOR doc IN FULLTEXT(testIndex, "complete:3da549f0-0e88-4297-b6af-5179b74bd929", "find") RETURN doc')
[object ArangoQueryCursor, count: 1, hasMore: false]
[
{
"_id" : "testIndex/4687201",
"_key" : "4687201",
"_rev" : "4687201",
"complete:3da549f0-0e88-4297-b6af-5179b74bd929" : "find me"
}
]
因此用例看起来不同:
db.test2.save({id: 'complete:3da549f0-0e88-4297-b6af-5179b74bd929'})
db.test2.ensureIndex({type: "fulltext", fields: ["id"]})
db._query('FOR doc IN FULLTEXT(test2, "id", "3da549f0-0e88-4297-b6af-5179b74bd929") RETURN doc')
这将 return 一个空结果。
要了解发生了什么,需要了解全文索引的工作原理。它在 word boundaries 处拆分文本并将其存储为一个列表,其中包含对索引中文档的引用。该索引全局词表中的一个词可能会引用多个文档。
查询索引后,将在索引全局词表中搜索请求的词,找到的每个词将包含包含该词的文档列表。这些桶被合并,returned 作为要迭代的文档的总列表。
了解the tokenizer a little better, I've added a tiny js wrapper that invokes it。
让我们看看它对您的字符串做了什么:
SYS_SPLIT_WORDS_ICU("ab cd", 0)
[
"ab",
" ",
"cd"
]
SYS_SPLIT_WORDS_ICU("3da549f0-0e88-4297-b6af-5179b74bd929", 0)
[
"3da549f0",
"-",
"0e88",
"-",
"4297",
"-",
"b6af",
"-",
"5179b74bd929"
]
所以你看,减号被视为单词边界,你的字符串被分区了。你现在有几个机会来规避这个:
- 删除插入的缺点
- 拆分搜索字符串,并使用散列中最有意义的部分,然后是实际值的 FILTER 语句
- 不要为此使用全文索引,而是使用跳过列表或哈希索引;它们的维护成本更低,可用于 FILTER 语句