Elasticsearch top_hits使用木瓦过滤器

时间:2015-05-11 13:46:06

标签: performance elasticsearch

我们正在使用Elasticsearch从大量数据集中的大约十二个不同字段中返回不同的搜索字词建议。为实现这一目标,我们目前正在使用'terms'和'top_hits'聚合(术语聚合使用通配符)。我们还在自定义分析器上使用shingle_filter(min-size:2,max-size:3),因为该项目的要求之一是返回多字搜索术语的搜索建议。

我尝试过几种不同的方法,但都不是很有效。

方法1 - _all

中的建议标准

我们想要返回建议的所有标准都放在_all字段中,该字段使用带有木瓦过滤器的自定义分析器:

'settings' : {
  'analysis' : {
    'analyzer' : {
      'autocomplete_analyzer' : {
        'type' : 'custom',
        'tokenizer' : 'suggestion_tokenizer',
        'filter' : [
          'lowercase',
           'shingle_filter'
        ]
      },
    },
    'tokenizer' : {
      'suggestion_tokenizer' : {
        'type' : 'whitespace'
      }
    },
    'filter' : {
      'shingle_filter' : {
        'type' : 'shingle',
        'min_shingle_size' : 2,
        'max_shingle_size' : 3
      }
    }
  }
},
'mappings' : {
  'core' : {
    '_all' : {
      'enabled' : 'yes',
      'index' : 'analyzed',
      'analyzer' : 'autocomplete_analyzer'
    },
    'properties' : {
      'suggestion_criteria_1': {
        'type' : 'multi_field',
        'fields' : {
          'analyzed' : {
            'type' : 'string',
            'index' : 'analyzed'
          },
          'suggestion_criteria_1': {
            'type' : 'string',
            'index' : 'not_analyzed',
            'include_in_all' : 'yes'
          }
        }
      },...
      'filter_criteria_1': {
        'type' : 'string',
        'include_in_all' : 'no',
        'index' : 'not_analyzed'
      },...
    }
  }
}

聚合/查询utilzies过滤器和建议术语搜索数组,因为我们需要知道建议匹配来自哪个字段:

{
  'from' : 0,
  'size' : 0,
  'query' : {
    'filtered' : {
      'filter' : {
        'and' : [
          {search filter array / optional}
        ]
      }
    }
  },
  'aggs' : {
    'suggestions' : {
      'terms' : {
        'field' : '_all',
        'include' : '.*{search_term}.*'
      },
      'aggs' : {
        'field_matches' : {
          'top_hits' : {
            '_source' : {
              'include' : {criteria_array}
            },
            'size' : 1
          }
        }
      }
    }
  }
};

在应用过滤器之后,我们正在处理一组大约10万个文档,结果会在500毫秒内返回,这比理想的搜索建议要长得多。

方法2 - 在聚合/丢弃_all

中包括所有建议标准

为简洁起见,我将仅描述上面的索引结构和查询/聚合的更改。

我禁用了_all字段,而是将“autocomplete_analyzer”(包括shingle_filter)应用于映射中的每个建议标准本身(其中大约有十几个)。

然后将所有建议条款添加到查询/聚合...

  'aggs' : {
    'suggestion_term_1' : {
      'terms' : {
        'field' : 'suggestion_term_1',
        'include' : '.*{search_term}.*'
      },
      'aggs' : {
        'field_matches' : {
          'top_hits' : {
            '_source' : {
              'include' : 'suggestion_term_1'
            },
            'size' : 1
          }
        }
      }
    },
    'suggestion_term_2' : {
      'terms' : {
        'field' : 'suggestion_term_2',
        'include' : '.*{search_term}.*'
      },
      'aggs' : {
        'field_matches' : {
          'top_hits' : {
            '_source' : {
              'include' : 'suggestion_term_2'
            },
            'size' : 1
          }
        }
      }
    },
    etc...
  }
};

一旦应用过滤器,这也会超过500毫秒。仍然不理想。

方法3 - 执行多个弹性搜索查询 - 迭代标准

这类似于方法2,但是不是在聚合中包括所有建议条款,而是在每个请求中仅包括一个术语。然后,我迭代建议条款,并为十几个标准中的每一个执行多个弹性搜索聚合请求。

大多数结果在20-30ms左右回来,但是当在整个迭代中求和时,我们在总请求时间内仍然在300-400ms之内。

Edge nGrams

我应该注意,作为使用通配符搜索词的替代方法,我也尝试将Edge nGram过滤器应用于分析器。然而,这通常会使总响应时间增加50-70%并使指数大小膨胀,从而没有明显的性能优势,因此我选择坚持使用通配符方法。

删除木瓦过滤器

我还应该注意到,当我删除木瓦过滤器时,我看到了显着的性能改进,但不幸的是,多字查询是项目的必要条件。

我怀疑可能有一两种方法我还没有尝试过,这会让我们显着提高性能时间,但在这一点上我基本上都在抓稻草。任何建议都将不胜感激。

0 个答案:

没有答案