在匹配嵌套/内部对象中的字段时连接 elasticsearch 索引



我正在尝试使用术语过滤器查找来连接 2 个弹性搜索索引。我提到了 http://www.elasticsearch.org/blog/terms-filter-lookup/和 http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html。这些示例查找一系列字段,如 "followers" : ["1", "3"] 和连接适用于类似的数据。

我的要求是与对象数组中的字段联接。当我扩展上述示例以包含对象数组时,我的查询失败。以下是示例数据:

PUT /users/user/2 {
   "followers" : [
  {
    "userId":"1",
    "username":"abc",
    "location":"xyz"
   },
   {
    "userId":"3",
    "username":"def",
    "location":"xyz"
   }
}
]
}
PUT /tweets/tweet/1 {
   "user" : "2"
}
PUT /tweets/tweet/2 {
   "user" : "1"
}

我现在正在尝试查找由用户 2 的关注者创建的推文

POST /tweets/_search {
  "query" : {
"filtered" : {
  "filter" : {
    "terms" : {
      "user" : {
        "index" : "users",
        "type" : "user",
        "id" : "2",
        "path" : "followers.userId"
      },
      "_cache_key" : "user_2_friends"
    }
  }
}
  }
}

对于上述查询,我的搜索结果为 0。我也尝试了其他 2 种方法 1(在映射期间将追随者对象声明为嵌套对象并在查询中使用"嵌套",2(在将路径作为"追随者"后尝试为 followers.userId 添加匹配查询。没有一个产生结果。

术语筛选器查找是否支持对象数组?解决我的问题的任何指示都会有很大帮助

你想做的事情对我有用,除非我错过了什么。您使用的是哪个版本的 Elasticsearch?我正在使用 1.3.4。

所以我创建了两个索引并添加了您列出的文档:

curl -XPUT "http://localhost:9200/users"
curl -XPUT "http://localhost:9200/users/user/2 " -d '
{
   "followers" : [
  {
    "userId":"1",
    "username":"abc",
    "location":"xyz"
   },
   {
    "userId":"3",
    "username":"def",
    "location":"xyz"
   }
   ]
}'
curl -XPUT "http://localhost:9200/tweets"
curl -XPUT "http://localhost:9200/tweets/tweet/1 " -d'
{
   "user" : "2"
}'
curl -XPUT "http://localhost:9200/tweets/tweet/2 " -d'
{
   "user" : "1"
}'

然后运行了您的搜索查询:

curl -XPOST "http://localhost:9200/tweets/_search " -d'
{
   "query": {
      "filtered": {
         "filter": {
            "terms": {
               "user": {
                  "index": "users",
                  "type": "user",
                  "id": "2",
                  "path": "followers.userId"
               },
               "_cache_key": "user_2_friends"
            }
         }
      }
   }
}'

并得到了这个结果:

{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "tweets",
            "_type": "tweet",
            "_id": "2",
            "_score": 1,
            "_source": {
               "user": "1"
            }
         }
      ]
   }
}

这是我使用的代码:

http://sense.qbox.io/gist/4a2a2d77d0b6f4502ff6c5022b268acfa65ee6d2

如果有索引,请清除索引

curl -XDELETE "http://example.com:9200/currencylookup/"
curl -XDELETE "http://example.com:9200/currency/"

创建查找表

curl -XPUT http://example.com:9200/currencylookup/type/2 -d '
{ "conv" : [ 
{  "currency":"usd","username":"abc", "location":"USA" }, 
{  "currency":"inr", "username":"def", "location":"India" },
{  "currency":"IDR", "username":"def", "location":"Indonesia" }]
}'

让我们放一些虚拟文档

curl -XPUT "http://example.com:9200/currency/type/USA" -d '{ "amount":"100", "currency":"usd", "location":"USA" }'
curl -XPUT "http://example.com:9200/currency/type/JPY" -d '{ "amount":"50", "currency":"JPY", "location":"JAPAN" }'
curl -XPUT "http://example.com:9200/currency/type/INR" -d '{ "amount":"50", "currency":"inr", "location":"INDIA" }'
curl -XPUT "http://example.com:9200/currency/type/IDR" -d '{ "amount":"30", "currency" : "IDR", "location": "Indonesia" }'

检查输出的时间

curl http://example.com:9200/currency/_search?pretty -d '{
   "query" : {
 "filtered" : {
   "filter" : {
     "terms" : {
       "currency" : {
         "index" : "currencylookup",
         "type" : "type",
         "id" : "2",
         "path" : "conv.currency"
       },
       "_cache_key" : "currencyexchange"
     }
   }
 }
   }
 }'

结果

# curl http://example.com:9200/currency/_search?pretty -d '{
   "query" : {
 "filtered" : {
   "filter" : {
     "terms" : {
       "currency" : {
         "index" : "currencylookup",
         "type" : "type",
         "id" : "2",
         "path" : "conv.currency"
       },
       "_cache_key" : "currencyexchange"
     }
   }
 }
   }
 }'
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "currency",
      "_type" : "type",
      "_id" : "INR",
      "_score" : 1.0,
      "_source":{ "amount":"50", "currency":"inr", "location":"INDIA" }
    }, {
      "_index" : "currency",
      "_type" : "type",
      "_id" : "USA",
      "_score" : 1.0,
      "_source":{ "amount":"100", "currency":"usd", "location":"USA" }
    } ]
  }
}

结论

大写字母是这里的罪魁祸首。

您可以看到">IDR"是大写的,所以匹配失败了,而"JPY">没有在查找中,即使它在那里也不会被匹配,因为它是大写的。

交叉匹配值必须为小写字母或数字,例如

例如:

  • 美国广播公司
  • 1ABC

最新更新