search method

Future<SearchResult> search({
  1. String? index,
  2. String? type,
  3. Map? query,
  4. int? offset,
  5. int? limit,
  6. List<Object>? fields,
  7. dynamic source,
  8. Map? suggest,
  9. List<Map>? sort,
  10. Map? aggregations,
  11. Duration? scroll,
  12. HighlightOptions? highlight,
  13. bool? trackTotalHits,
  14. int? size,
  15. double? minScore,
})

Search :-)

Implementation

Future<SearchResult> search({
  String? index,
  String? type,
  Map? query,
  // TODO: investigate if/when this should be deprecated in favour of `from`
  int? offset,
  // TODO: investigate if/when this should be deprecated in favour of `size`
  int? limit,
  List<Object>? fields,
  dynamic source,
  Map? suggest,
  List<Map>? sort,
  Map? aggregations,
  Duration? scroll,
  HighlightOptions? highlight,
  bool? trackTotalHits,
  int? size,
  double? minScore,
}) async {
  final path = [
    if (index != null) index,
    if (type != null) type,
    '_search',
  ];

  final map = {
    if (source != null) '_source': source,
    if (fields != null) 'fields': fields,
    'query': query ?? Query.matchAll(),
    if (offset != null) 'from': offset,
    if (limit != null) 'size': limit,
    if (suggest != null) 'suggest': suggest,
    if (sort != null) 'sort': sort,
    if (aggregations != null) 'aggregations': aggregations,
    if (highlight != null) 'highlight': highlight.toMap(),
    if (trackTotalHits != null) 'track_total_hits': trackTotalHits,
    if (size != null) 'size': size,
    if (minScore != null) 'min_score': minScore,
  };
  final params = {
    'search_type': 'dfs_query_then_fetch',
    if (scroll != null) 'scroll': scroll.inSeconds.toString() + 's',
  };
  final rs = await _transport
      .send(Request('POST', path, params: params, bodyMap: map));
  rs.throwIfStatusNotOK(message: 'Failed to search $query.');
  final body = rs.bodyAsMap;
  final hitsMap = body['hits'] as Map<String, dynamic>? ?? const {};
  final totalCount = _extractTotalCount(hitsMap);
  final results = _extractDocList(hitsMap);
  final suggestMap = body['suggest'] as Map? ?? const {};
  final suggestEntries =
      suggestMap.entries.where((e) => e.value != null).map((e) {
    final list = (e.value as List).cast<Map>();
    final hits = list.map((map) {
      final optionsList = (map['options'] as List).cast<Map>();
      final options = optionsList.map((m) {
        return SuggestHitOption(
          m['text'] as String,
          m['score'] as double,
          freq: (m['freq'] ?? -1) as int,
          highlighted: m['highlighted'] as String,
        );
      }).toList();
      return SuggestHit(
        map['text'] as String,
        map['offset'] as int,
        map['length'] as int,
        options,
      );
    }).toList();
    return MapEntry('', hits);
  });
  final suggestHits = Map.fromEntries(suggestEntries);

  final aggMap = body['aggregations'] as Map<String, dynamic>? ?? const {};
  final aggResult = aggMap.map<String, Aggregation>((k, v) {
    final agg = Aggregation(k, aggregations![k] as Map<String, dynamic>,
        v as Map<String, dynamic>);
    return MapEntry(k, agg);
  });

  return SearchResult(
    totalCount,
    results,
    suggestHits: suggestHits.isEmpty ? null : suggestHits,
    aggregations: aggResult.isEmpty ? null : aggResult,
    scrollId: body['_scroll_id'] as String?,
  );
}