如何使用任意数量的字段搜索数据?

时间:2014-08-17 09:52:42

标签: search elasticsearch full-text-search search-engine

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

创建的表单用于:

  • 向活动注册新会员;
  • 搜索注册会员。

第二项任务的最佳搜索工具是什么(搜索事件的成员)? ElasticSearch能很好地完成这项任务吗?

3 个答案:

答案 0 :(得分:0)

ElasticSearch会自动检测字段内容,以便正确地对其进行索引,即使之前未定义映射也是如此。所以,是的:ElasticSearch非常适合这些案例。

但是,您可能希望微调此行为,或者ElasticSearch应用的默认映射可能与您需要的内容不对应:在这种情况下,请查看default mapping或更进一步控制,dynamic templates功能。

答案 1 :(得分:0)

如果您允许最终用户决定密钥,那么您将拥有不断增长的映射和群集状态,这是有问题的。

此案例和建议的解决方案包含在此article on common problems with Elasticsearch

基本上,您希望将所有可能由用户定义的值作为值。使用嵌套文档,您可以使用key字段和不同映射的值字段来实现几乎相同。

答案 2 :(得分:0)

我写了一篇关于如何将任意数据索引到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对象执行查询以查找所需内容。
  6. 示例

    根据您的原始问题,我们假设第一个活动主持人创建了一个包含以下字段的表单来注册科学活动的成员:

    • 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,他的表单将允许在两个字符串之间进行选择 - "男性"和女性"。

    让我们尝试压缩此表单提交的数据:

    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之后,我们可以执行复杂的查询。

    例如,要找到名为" Bob"注册ID为2T73ZT1R463DJNWE36IA8FEN的活动,我们可以执行以下查询:

    {
        "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"}}
                                    ]
                                }
                            }
                        }
                    }
                ]
            }
        }
    }