改写:
在我的项目中,我有图像.每个图像都有5个范围[1,10]的标签.我使用Elasticsearch上传这些标签:
我将这些文档加载到索引"my_project"中的elasticsearch中,类型为"img":
curl -XPUT 'http://localhost:9200/my_project/img/1' -d ' {"tags": [1,4,6,7,9]} '
我上传的其他示例文档:
{"tags": [1,4,6,7]} {"tags": [2,3,5,6]} {"tags": [1,2,3,8]}
在我的应用程序中,向量更长,但具有固定数量的唯一元素.而且我喜欢这些文件的20M.
现在我想找到给定向量的类似文档.当矢量具有更常见的标签时,矢量更相似.因此,例如,我想找到整数向量的大多数类似文档[1,2,3,7]
.最佳匹配应该是最后一个示例文档{"tags": [1,2,3,8]}
,因为它们在其标记中共享3个公共值,[1,2,3]
比任何其他向量更常见的值.
所以这是我的问题.如果我使用上面的CURL命令上传文档,我会得到以下映射:
{ "my_project" : { "mappings" : { "img" : { "properties" : { "tags" : { "type" : "string" } } } } } }
但我认为正确的映射应该使用整数而不是字符串.如何为此类数据进行正确的显式映射?
现在我想用上面的相似度算法搜索文档.如何使用上面解释的相似度算法获得上述类型的100个最相似的文档?如果我将这些向量转换为具有空格分隔数字的字符串,我将能够使用带有for语句的布尔查询进行此搜索,但我认为使用整数数组应该更快.你能告诉我,我怎样才能为elasticsearch构建搜索查询?
我现在使用的基本解决方案是将整数数组转换为字符串.所以我将文件保存为:
curl -XPUT 'http://localhost:9200/my_project/img/1' -d ' {"tags": "1 4 6 7 9"} '
然后基本上搜索字符串"1 2 3"
.虽然这在某种程度上起作用,但我认为将整数数组保存为整数数组而不是字符串会更正确和更快.是否可以像使用整数数组一样使用elasticsearch中的整数数组?也许我的字符串方法是最好的,不能/不必在elasticsearch中显式使用整数数组.
您可以使用使用欧几里德距离公式的功能评分查询来获得您想要的内容.
删除当前映射并索引文档:
curl -XPUT 'http://localhost:9200/my_project/img/1' -d ' { "tags": { "tag1": 1, "tag2": 4, "tag3": 6, "tag4": 7 } }' curl -XPUT 'http://localhost:9200/my_project/img/2' -d ' { "tags": { "tag1": 2, "tag2": 3, "tag3": 5, "tag4": 6 } }' curl -XPUT 'http://localhost:9200/my_project/img/3' -d ' { "tags": { "tag1": 1, "tag2": 2, "tag3": 3, "tag4": 8 } }'
停止Elasticsearch并创建一个名为'euclidian_distance.mvel'的脚本文件$ES_HOME/config/scripts
并添加此脚本.
_score * pow(sqrt(pow(doc['tags.tag1'].value - param1, 2)) + sqrt(pow(doc['tags.tag2'].value - param2, 2)) + sqrt(pow(doc['tags.tag3'].value - param3, 2)) + sqrt(pow(doc['tags.tag4'].value - param4, 2)), -1)
重新启动Elastisearch并运行此查询:
curl -XPOST 'http://localhost:9200/my_project/' -d ' { "query": { "function_score": { "query": { "match_all": {} }, "script_score": { "script": "euclidian_distance", "params": { "param1": 1, "param2": 2, "param3": 3, "param4": 7 } } } } }
1,2,3,8
将首先返回带有值的标记对象.