8

我正在尝试确定在弹性搜索中索引文档的最佳方法。我有一个文档 Doc,其中包含一些字段:

Doc
  created_at
  updated_at
  field_a
  field_b

但是 Doc 也会有一些特定于个人用户的字段。例如,对于用户 1,field_x 的值为“A”,对于用户 2,field_x 的值为“B”。对于每个文档,用户数量非常有限(通常为 2,最多约 10 个)。当用户搜索 field_x 时,他们必须搜索属于他们的值。我一直在探索 ES 中的嵌套类型。

Doc
  created_at
  updated_at
  field_x: [{
    user: 1
    field_x: A
  },{
    user: 2
    field_x: B
  }]

当用户 1 在 field_x 上搜索值 'A' 时,此文档应该会导致命中。但是,当用户 1 按值“B”搜索时,它不应该。

但是,根据文档

索引文档中多次出现的内部对象时的问题之一是会发生“跨对象”搜索匹配

有没有办法避免嵌套类型的这种行为,或者我应该探索另一种类型?

有关此类查询性能的其他信息将非常有价值。仅仅通过阅读文档,它就表明嵌套查询在性能方面与常规查询没有太大区别。如果有人有这方面的真实经历,我很想听听。

4

1 回答 1

6

嵌套类型就是你要找的,不用太担心性能。

在索引文档之前,您需要为文档设置映射:

curl -XDELETE localhost:9200/index
curl -XPUT localhost:9200/index
curl -XPUT localhost:9200/index/type/_mapping -d '{
    "type": {
        "properties": {
            "field_x": {
                "type": "nested",
                "include_in_parent": false,
                "include_in_root": false,
                "properties": {
                    "user": {
                        "type": "string"
                    },
                    "field_x": {
                        "type": "string",
                        "index" : "not_analyzed" // NOTE*
                    }
                }
            }
        }
    }
}'

*注意:如果你的字段真的只包含像“A”和“B”这样的单数字母,则不要分析该字段,否则elasticsearch会删除这些单数字母“单词”。如果这只是您的示例,并且在您的真实文档中您正在搜索正确的单词,请删除此行并让 elasticsearch 分析该字段。

然后,索引您的文档:

curl -XPUT http://localhost:9200/index/type/1 -d '
{ 
    "field_a": "foo",
    "field_b": "bar",
    "field_x" : [{
        "user" : "1",
        "field_x" : "A"
    },
    {
        "user" : "2",
        "field_x" : "B"
    }]
}'

并运行您的查询:

curl -XGET localhost:9200/index/type/_search -d '{ 
    "query": {
        "nested" : {
            "path" : "field_x",
            "score_mode" : "avg",
            "query" : {
                "bool" : {
                    "must" : [
                        {
                            "term": {
                                "field_x.user": "1"
                            }
                        },
                        {
                            "term": {
                                "field_x.field_x": "A"
                            }
                        }
                    ]
                }
            }
        }
    }
}';

这将导致

{"took":13,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":1,"max_score":1.987628,"hits":[{"_index":"index","_type":"type","_id":"1","_score":1.987628, "_source" : 
{ 
    "field_a": "foo",
    "field_b": "bar",
    "field_x" : [{
        "user" : "1",
        "field_x" : "A"
    },
    {
        "user" : "2",
        "field_x" : "B"
    }]
}}]}}

然而,查询

curl -XGET localhost:9200/index/type/_search -d '{ 
    "query": {
        "nested" : {
            "path" : "field_x",
            "score_mode" : "avg",
            "query" : {
                "bool" : {
                    "must" : [
                        {
                            "term": {
                                "field_x.user": "1"
                            }
                        },
                        {
                            "term": {
                                "field_x.field_x": "B"
                            }
                        }
                    ]
                }
            }
        }
    }
}';

不会返回任何结果

{"took":6,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}}
于 2013-07-09T08:09:36.110 回答