繁体   English   中英

如何通过任意数量的字段搜索数据?

[英]How to search through data with arbitrary amount of fields?

我有科学活动的网络表单生成器。 事件主持人使用任意数量的布尔值,整数,枚举和文本字段创建注册表单。

创建的表单用于:

  • 注册新会员参加活动;
  • 通过注册会员搜索。

什么是第二项任务(搜索事件成员)的最佳搜索工具? ElasticSearch是否适合此任务?

ElasticSearch自动检测字段内容以正确索引它,即使以前未定义映射。 所以,是的:ElasticSearch非常适合这些情况。

但是,您可能想微调此行为,或者ElasticSearch应用的默认映射可能与您所需的不符:在这种情况下,请查看默认映射,或者甚至进一步控制动态模板功能。

如果让最终用户决定存储事物的密钥 ,则映射和集群状态将不断增长,这是有问题的。

关于Elasticsearch的常见问题,本文讨论了这种情况和建议的解决方案。

本质上,您希望拥有可以由用户定义为值的所有内容。 使用嵌套文档,您可以拥有一个key字段和不同映射的值字段,以实现几乎相同的效果。

我写了一篇关于如何将任意数据索引到Elasticsearch中,然后按特定字段和值搜索它的文章。 所有这一切,都不会破坏索引映射。

帖子在这里: http : //smnh.me/indexing-and-searching-arbitrary-json-data-using-elasticsearch/

简而言之,您将需要执行以下步骤以获取所需的内容:

  1. 创建帖子中描述的特殊索引。
  2. 使用flattenData函数展平要索引的数据:
    https://gist.github.com/smnh/30f96028511e1440b7b02ea559858af4
  3. 使用原始数据和展平的数据创建文档,并将其索引到Elasticsearch中:

     { "data": { ... }, "flatData": [ ... ] } 
  4. 可选:使用Elasticsearch聚合来查找已索引哪些字段和类型。

  5. flatData对象执行查询以查找所需内容。

基于您的原始问题,让我们假设第一个事件主持人创建了一个包含以下字段的表单,以注册科学事件的成员:

  • name 字符串
  • age
  • sex -男性0 ,女性1

除了这些数据之外,相关事件可能还具有某种ID,我们将其称为eventId 因此最终文档可能如下所示:

{
    "eventId": "2T73ZT1R463DJNWE36IA8FEN",
    "name": "Bob",
    "age": 22,
    "sex": 0
}

现在,在索引此文档之前,我们将使用flattenData函数对其进行展平:

flattenData(document);

这将产生以下数组:

[
    {
        "key": "eventId",
        "type": "string",
        "key_type": "eventId.string",
        "value_string": "2T73ZT1R463DJNWE36IA8FEN"
    },
    {
        "key": "name",
        "type": "string",
        "key_type": "name.string",
        "value_string": "Bob"
    },
    {
        "key": "age",
        "type": "long",
        "key_type": "age.long",
        "value_long": 22
    },
    {
        "key": "sex",
        "type": "long",
        "key_type": "sex.long",
        "value_long": 0
    }
]

然后,我们将把这些数据包装到我之前显示的文档中并对其进行索引。

然后,第二个事件主持人创建另一个具有新字段的表单,该字段具有相同名称和类型的字段,以及具有相同名称但类型不同的字段:

  • name 字符串
  • city 字符串
  • sex 字符串 -“男性”或“女性”

该事件主持人决定,男性和女性的形式不必为01 ,而是可以在两个字符串之间进行选择-“ male”和“ female”。

让我们尝试展平此表单提交的数据:

flattenData({
    "eventId": "F1BU9GGK5IX3ZWOLGCE3I5ML",
    "name": "Alice",
    "city": "New York",
    "sex": "female"
});

这将产生以下数据:

[
    {
        "key": "eventId",
        "type": "string",
        "key_type": "eventId.string",
        "value_string": "F1BU9GGK5IX3ZWOLGCE3I5ML"
    },
    {
        "key": "name",
        "type": "string",
        "key_type": "name.string",
        "value_string": "Alice"
    },
    {
        "key": "city",
        "type": "string",
        "key_type": "city.string",
        "value_string": "New York"
    },
    {
        "key": "sex",
        "type": "string",
        "key_type": "sex.string",
        "value_string": "female"
    }
]

然后,在将扁平化数据包装在文档中并将其编入Elasticsearch后,我们可以执行复杂的查询。

例如,要查找为事件注册的ID为2T73ZT1R463DJNWE36IA8FEN名为“ Bob”的成员,我们可以执行以下查询:

{
    "query": {
        "bool": {
            "must": [
                {
                    "nested": {
                        "path": "flatData",
                        "query": {
                            "bool": {
                                "must": [
                                    {"term": {"flatData.key": "eventId"}},
                                    {"match": {"flatData.value_string.keyword": "2T73ZT1R463DJNWE36IA8FEN"}}
                                ]
                            }
                        }
                    }
                },
                {
                    "nested": {
                        "path": "flatData",
                        "query": {
                            "bool": {
                                "must": [
                                    {"term": {"flatData.key": "name"}},
                                    {"match": {"flatData.value_string": "bob"}}
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM