performDocumentSearch method

  1. @override
Stream<QueryResult> performDocumentSearch (
  1. DocumentSearchRequest request
)
override

Implementation

@override
Stream<QueryResult> performDocumentSearch(
    DocumentSearchRequest request) async* {
  final queryArguments = <String, String>{};

  // Validate index name
  final collection = request.collection;
  final collectionId = _validateCollectionId(collection.collectionId);

  final query = request.query ?? const Query();

  // Query string
  {
    final filter = query.filter;
    if (filter != null) {
      queryArguments['query'] = filter.toString();
    }
  }

  if (query.sorter != null && allowSortersByIgnoring == false) {
    // Sorting order is not supported by Algolia.
    // Each index can have only one sorting order.
    throw UnsupportedError('Sorting is not supported by Algolia');
  }

  // Skip
  var hasSkipOrTake = false;
  {
    final skip = query.skip;
    if (skip != 0) {
      hasSkipOrTake = true;
      queryArguments['offset'] = skip.toString();
    }
  }

  // Take
  {
    final take = query.take;
    if (take != null && take != 0) {
      hasSkipOrTake = true;
      queryArguments['length'] = take.toString();
    }
  }

  // Algolia requires both to be present if one is present
  if (hasSkipOrTake) {
    queryArguments['offset'] ??= '0';
    queryArguments['length'] ??= '10';
  }

  // Dispatch request
  final apiResponse = await _apiRequest(
    method: 'GET',
    path: '/1/indexes/$collectionId',
    queryParameters: queryArguments,
  );

  if (apiResponse.statusCode == HttpStatus.notFound) {
    //
    // No such collection
    //
    yield (QueryResult(
      collection: collection,
      query: query,
      snapshots: const <Snapshot>[],
    ));
    return;
  }

  final error = apiResponse.error;
  if (error != null) {
    throw error;
  }

  final jsonHitsList = apiResponse.json['hits'] as List<Object>;

  final items =
      List<QueryResultItem>.unmodifiable(jsonHitsList.map((jsonHit) {
    if (jsonHit is Map<String, Object>) {
      //
      // Declare locals
      //
      String documentId;
      final data = <String, Object>{};
      double score;

      //
      // Visit all properties
      //
      jsonHit.forEach((name, value) {
        switch (name) {
          case 'objectID':
            documentId = value as String;
            break;
          case '_rankingInfo':
            if (value is Map) {
              score = (value['userScore'] as num).toDouble();
            }
            break;
          default:
            data[name] = value;
            break;
        }
      });

      //
      // Return snapshot
      //
      return QueryResultItem(
        vendorData: jsonHit,
        snapshot: Snapshot(
          document: collection.document(documentId),
          data: data,
        ),
        score: score,
      );
    } else {
      throw ArgumentError.value(jsonHit);
    }
  }));

  yield (QueryResult.withDetails(
    vendorData: apiResponse.json,
    collection: collection,
    query: query,
    items: items,
  ));
}