我有两个索引 - 一个包含带有_id=<url of the document>
的“文档”对象,例如http://site/folder/document_name.doc
;另一个包含带有_id=<url of the folder>
的“文件夹”对象,例如http://site/folder
在我的node.js脚本中,我需要将文档与文件夹匹配,即我搜索所有文件夹网址,然后为每个文件夹搜索所有文件,这些网址以文件夹url开头
我似乎无法构建正确的查询,该查询将返回_id
以http://site/folder
开头的所有文档
有什么想法吗?
答案 0 :(得分:3)
我认为更好的解决方案是不要将_id
用于此问题。
相反,索引字段名为path
(或您想要的任何名称),并使用Path Hierarchy Tokenizer查看一些创意代币过滤器。
这样您就可以使用Elasticsearch / Lucene来标记URL。
例如:https://site/folder
被标记为两个标记:
site
site/folder
然后,您可以通过搜索正确的令牌来site
文件夹中包含的任何文件或文件夹:site
。
PUT /test
{
"settings": {
"analysis": {
"filter": {
"http_dropper": {
"type": "pattern_replace",
"pattern": "^https?:/{0,}(.*)",
"replacement": "$1"
},
"empty_dropper": {
"type": "length",
"min": 1
},
"qs_dropper": {
"type": "pattern_replace",
"pattern": "(.*)[?].*",
"replacement": "$1"
},
"trailing_slash_dropper": {
"type": "pattern_replace",
"pattern": "(.*)/+$",
"replacement": "$1"
}
},
"analyzer": {
"url": {
"tokenizer": "path_hierarchy",
"filter": [
"http_dropper",
"qs_dropper",
"trailing_slash_dropper",
"empty_dropper",
"unique"
]
}
}
}
},
"mappings": {
"type" : {
"properties": {
"url" : {
"type": "string",
"analyzer": "url"
},
"type" : {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
您可能或可能不想要我添加的trailing_slash_dropper
。在那里使用lowercase
令牌过滤器也是值得的,但这实际上可能会使某些URL令牌从根本上不正确(例如,mysite.com/bucket/AaDsaAe31AcxX
可能真的关心这些字符的情况)。您可以使用_analyze
端点将分析仪用于试驾:
GET /test/_analyze?analyzer=url&text=http://test.com/text/a/?value=xyz&abc=value
注意:我正在使用Sense,所以它为我做了URL编码。这将产生三个令牌:
{
"tokens": [
{
"token": "test.com",
"start_offset": 0,
"end_offset": 15,
"type": "word",
"position": 0
},
{
"token": "test.com/text",
"start_offset": 0,
"end_offset": 20,
"type": "word",
"position": 0
},
{
"token": "test.com/text/a",
"start_offset": 0,
"end_offset": 22,
"type": "word",
"position": 0
}
]
}
将它们捆绑在一起:
POST /test/type
{
"type" : "dir",
"url" : "https://site"
}
POST /test/type
{
"type" : "dir",
"url" : "https://site/folder"
}
POST /test/type
{
"type" : "file",
"url" : "http://site/folder/document_name.doc"
}
POST /test/type
{
"type" : "file",
"url" : "http://other/site/folder/document_name.doc"
}
POST /test/type
{
"type" : "file",
"url" : "http://other_site/folder/document_name.doc"
}
POST /test/type
{
"type" : "file",
"url" : "http://site/mirror/document_name.doc"
}
GET /test/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"url": "http://site/folder"
}
}
],
"filter": [
{
"term": {
"type": "file"
}
}
]
}
}
}
对此进行测试非常重要,这样您就可以看到匹配的内容以及这些匹配的顺序。当然,这会找到您希望它找到的文档(并将其置于顶部!),但它也会找到您可能不期望的其他文档,例如http://site/mirror/document_name.doc
,因为它共享基本标记:{{1 }}。您可以使用一系列策略来排除这些文档如果排除它们很重要。
您可以利用标记化来执行类似Google的结果过滤,例如如何通过Google搜索特定域名:
匹配查询网站:elastic.co
然后您可以解析(手动)site
并将site:elastic.co
作为边界网址:
elastic.co
请注意,这与搜索网址不同。您明确说“只包含在其网址中包含此完全标记的文档”。您可以使用{
"term" : {
"url" : "elastic.co"
}
}
等进一步,因为存在确切的令牌。但是,重要的是要注意,如果您要尝试site:elastic.co/blog
,那么就找不到任何文档,因为在令牌过滤器的情况下该令牌不存在。