php - 使用elasticsearch,如何为包含数组的文档创建索引,并在将来追加到该数组

标签 php arrays elasticsearch

在我的示例代码中,我使用的是 php 客户端库,但任何熟悉 elasticsearch 的人都应该理解它。

我正在使用 elasticsearch 创建一个索引,其中每个文档都包含一组 nGram 索引作者。最初,该文档将只有一个作者,但随着时间的推移,更多的作者将被附加到数组中。理想情况下,可以通过作者的姓名执行搜索,如果数组中的任何作者匹配,就会找到该文档。

我一直在尝试使用文档 here用于追加到数组和 here使用数组类型 - 但我没有成功地让它工作。

首先,我想为文档创建一个索引,其中包含标题、作者数组和评论数组。

$client = new Client();
$params = [
    'index' => 'document',
    'body' => [
        'settings' => [
            // Simple settings for now, single shard
            'number_of_shards' => 1,
            'number_of_replicas' => 0,
            'analysis' => [
                'filter' => [
                    'shingle' => [
                        'type' => 'shingle'
                    ]
                ],
                'analyzer' => [
                    'my_ngram_analyzer' => [
                        'tokenizer' => 'my_ngram_tokenizer',
                        'filter' => 'lowercase',
                    ]
                ],
                // Allow searching for partial names with nGram
                'tokenizer' => [
                    'my_ngram_tokenizer' => [
                        'type' => 'nGram',
                        'min_gram' => 1,
                        'max_gram' => 15,
                        'token_chars' => ['letter', 'digit']
                    ]
                ]
            ]
        ],
        'mappings' => [
            '_default_' => [
                'properties' => [
                    'document_id' => [
                        'type' => 'string',
                        'index' => 'not_analyzed',
                    ],
                    // The name, email, or other info related to the person
                    'title' => [
                        'type' => 'string',
                        'analyzer' => 'my_ngram_analyzer',
                        'term_vector' => 'yes',
                        'copy_to' => 'combined'
                    ],
                    'authors' => [
                        'type' => 'list',
                        'analyzer' => 'my_ngram_analyzer',
                        'term_vector' => 'yes',
                        'copy_to' => 'combined'
                    ],
                    'comments' => [
                        'type' => 'list',
                        'analyzer' => 'my_ngram_analyzer',
                        'term_vector' => 'yes',
                        'copy_to' => 'combined'
                    ],
                ]
            ],
        ]
    ]
];
// Create index `person` with ngram indexing
$client->indices()->create($params);

一开始,由于此错误,我什至无法创建索引:
{"error":"MapperParsingException[mapping [_default_]]; nested: MapperParsingException[No handler for type [list] declared on field [authors]]; ","status":400}

如果这成功了,我会计划创建一个索引,从作者和标题的空数组开始,如下所示:
    $client = new Client();
    $params = array();
    $params['body']  = array('document_id' => 'id_here', 'title' => 'my_title', 'authors' => [], 'comments' => []);
    $params['index'] = 'document';
    $params['type']  = 'example_type';
    $params['id'] = 'id_here';
    $ret = $client->index($params);
    return $ret;

如果我有所需的索引来添加这种信息结构,这似乎应该可以工作,但我担心的是使用 update 将一些东西附加到数组中。 .例如,
    $client = new Client();
    $params = array();
    //$params['body']  = array('person_id' => $person_id, 'emails' => [$email]);
    $params['index'] = 'document';
    $params['type']  = 'example_type';
    $params['id'] = 'id_here';
    $params['script'] = 'NO IDEA WHAT THIS SCRIPT SHOULD BE TO APPEND TO THE ARRAY';
    $ret = $client->update($params);
    return $ret;
}

我不确定我将如何实际将一个东西附加到数组并确保它被索引。

最后,让我感到困惑的另一件事是如何根据数组中的任何作者进行搜索。理想情况下,我可以做这样的事情:

但我不是 100% 它是否会起作用。也许我不理解 Elasticsearch 的一些基本内容。我是全新的,所以任何能让我达到这些小细节不会让我挂断电话的资源将不胜感激。

此外,任何有关如何使用 Elasticsearch 来解决这些问题的直接建议都将不胜感激。

对不起,文字的大墙,回顾一下,我正在寻找关于如何做的建议
  • 创建支持对数组的所有元素进行 nGram 分析的索引
  • 更新该索引以追加到数组
  • 搜索现在更新的索引。

  • 谢谢你的帮助

    编辑:感谢@atax,我现在能够创建索引并作为字符串附加到值。但是,这样做有两个问题:
  • 数组存储为字符串值,所以像
  • 这样的脚本
    $params['script'] = 'ctx._source.authors += [\'hello\']';
    实际上附加了一个带有 [] 的字符串而不是包含值的数组。
  • 输入的值似乎不是 ngram 分析的,所以这样的搜索:

    $client = 新客户();
    $searchParams['index'] = 'document';
    $searchParams['type'] = 'example_type';
    $searchParams['body']['query']['match']['_all'] = '你好';
    $queryResponse = $client->search($searchParams);
    print_r($queryResponse);//成功

  • 将找到新值,但搜索如下:
    $client = new Client();
    $searchParams['index'] = 'document';
    $searchParams['type']  = 'example_type';
    $searchParams['body']['query']['match']['_all'] = 'hel';
    $queryResponse = $client->search($searchParams);
    print_r($queryResponse); // NO RESULTS
    

    才不是

    最佳答案

    elasticsearch 中没有“list”类型。但是您可以使用“字符串”字段类型并存储值数组。

                    ....
                    'comments' => [
                        'type' => 'string',
                        'analyzer' => 'my_ngram_analyzer',
                        'term_vector' => 'yes',
                        'copy_to' => 'combined'
                    ],
                    ....
    

    并以这种方式索引文档:
    ....
    $params['body']  = array(
       'document_id' => 'id_here',
       'title' => 'my_title',
       'authors' => [],
       'comments' => ['comment1', 'comment2']);
    ....
    

    至于将元素附加到数组的脚本,这个答案可能会对您有所帮助 - Elasticsearch upserting and appending to array

    但是,您真的需要更新文档吗?重新索引它可能更容易,因为这正是 Elasticsearch 在内部所做的。它读取“_source”属性,进行所需的修改并重新索引它。顺便说一句,这意味着必须启用“_source”并且文档的所有属性都应该包含在其中。

    您也可以考虑将评论和作者(据我了解,这些是评论的作者,而不是文档作者)存储为 ES 中的子文档并使用“has_child”过滤器。

    我真的不能给你具体的解决方案,但强烈建议为 ElasticSearch 安装 Marvel 插件,并使用它的“感觉”工具来逐步检查你的整个过程是如何工作的。

    因此,通过运行 http://www.elastic.co/guide/en/elasticsearch/reference/1.4/indices-analyze.html 中所述的测试来检查您的标记器是否正确配置。 .

    然后通过运行 GET/document/example_type/some_existing_id 检索文档来检查您的更新脚本是否正在执行您的预期
    作者和评论应该是数组,而不是字符串。

    最后执行搜索:
    GET /document/_search { 'query' : { 'match': { '_all': 'hel' } } }
    如果您自己构建查询而不是从用户那里获取,您可以使用 query_string 和占位符:
    GET /document/_search { 'query' : { 'query_string': { 'fields': '_all', 'query': 'hel*' } } }

    关于php - 使用elasticsearch,如何为包含数组的文档创建索引,并在将来追加到该数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29541994/

    相关文章:

    php - 从 html 表单发布到 onesignal php Api?

    php - 在zend framework 2中实现登录功能

    php - 正则表达式,贪婪 |

    api - 如何通过 API 调用将 kibana(ELK 堆栈)中的数据导出为 CSV?

    elasticsearch - 通配符查询 Elasticsearch 不适用于多词值

    php - 有什么好的允许列出资源的PHP权限框架?

    javascript - 在 Javascript 中从对象内部引用对象的数组

    javascript - 使用另一个日期数组删除日期数组

    Java:使用 int 数组调用 Object vararg 方法

    java - Elasticsearch MultiSearchRequestBuilder