You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Algolia中显示带计数的分面(Facet)

问题:Algolia searchResponse.facets 始终为空

我正尝试获取已配置的分面列表,配置方式参考Algolia官方文档。我同时使用了Algolia新官方包和非官方包进行设置,原本以为官方包会改变响应结果。尽管浏览器控制台中一切看似符合预期,但searchResponse.facets始终为空。相关代码如下:

import 'dart:async';
import 'dart:io';

import 'package:algolia/algolia.dart';
import 'package:algolia_helper_flutter/algolia_helper_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:masterecommerce/src/constants/app_sizes.dart';
import 'package:masterecommerce/src/exceptions/app_exception.dart';
import 'package:masterecommerce/src/features/menu/presentation/search_header.dart';
import 'package:masterecommerce/src/features/products/domain/algolia_output.dart';
import 'package:masterecommerce/src/features/products/domain/algolia_params.dart';

import '../constants/credentials.dart';
import '../features/products/domain/product.dart';
import 'firestore_service.dart';

final searchResponseProvider = StateProvider.autoDispose<SearchResponse>((ref) {
  return SearchResponse({});
});
final searchStateProvider = StateProvider.autoDispose<SearchState>((ref) {
  return const SearchState(indexName: kIndexName);
});
final algoliaInputProvider = StateProvider.autoDispose<AlgoliaInput>((ref) {
  return const AlgoliaInput();
});

final algoliaControllerProvider = StateNotifierProvider.autoDispose<
    AlgoliaController, AsyncValue<List<Product>>>((ref) {
  return AlgoliaController(
      ref: ref, algoliaInput: ref.watch(algoliaInputProvider));
});

final algoliaControllerSearchProvider = StateNotifierProvider.autoDispose<
    AlgoliaController, AsyncValue<List<Product>>>((ref) {
  return AlgoliaController(
      ref: ref,
      algoliaInput: AlgoliaInput(
          query: ref.watch(currentQuerySearchProvider), hitsPerPage: 3));
});

class AlgoliaController extends StateNotifier<AsyncValue<List<Product>>> {
  StreamSubscription? subResponses;
  StreamSubscription? subSearchState;

  late HitsSearcher searcher;
  late Algolia algoliaForSettings;
  final Ref ref;
  final AlgoliaInput algoliaInput;

  AlgoliaController({required this.ref, required this.algoliaInput})
      : super(const AsyncLoading()) {
    algoliaForSettings = const Algolia.init(
        applicationId: algoliaKeyAppId, apiKey: algoliaKeyCustom);
    searcher = HitsSearcher(
      applicationID: algoliaKeyAppId,
      apiKey: algoliaKeyCustom,
      indexName: kIndexName,
    );

    subResponses = searcher.responses.handleError((onError) {
      print(onError);
      state = AsyncError(onError);
    }).listen((searchResponse) {
      print(searchResponse.facets);
      print(searchResponse.raw["facets"]);
      ref.read(searchResponseProvider.state).update((state) => searchResponse);
      
      final products = searchResponse.hits
          .map((e) => Product.fromMapAlgolia(e.cast()))
          .toList();
      if (mounted) {
        state = AsyncValue<List<Product>>.data(products);
      }
    });

    subSearchState = searcher.state.handleError((onError) {
      print(onError);
      state = AsyncError(onError);
    }).listen((searchState) {
      ref.read(searchStateProvider.state).update((state) => searchState);
    });

    _newAlgoliaState(algoliaInput: algoliaInput);
  }

  @override
  void dispose() {
    searcher.dispose();
    subResponses?.cancel();
    subSearchState?.cancel();
    super.dispose();
  }

  Future<void> _newAlgoliaState({required AlgoliaInput algoliaInput}) async {
    state = const AsyncLoading();

    final algoliaOutput = algoliaInput.toAlgoliaOutput();
    await _setAlgoliaRanking(algoliaOutput: algoliaOutput);
    if (!mounted) {
      return;
    }
    searcher.connectFilterState(algoliaOutput.filterState);
    searcher.applyState((state) => algoliaOutput.toSearchState());
  }

  Future<void> _setAlgoliaRanking(
      {required AlgoliaOutput algoliaOutput}) async {
    AlgoliaIndexReference algoliaIndexReference =
        algoliaForSettings.instance.index("products");
    final ranking = algoliaOutput.ranking;
    if (ranking != null && ranking.isNotEmpty) {
      AlgoliaTask algoliaTask =
          await algoliaIndexReference.settings.setRanking([
        ...ranking,
        "typo",
        "geo",
        "words",
        "filters",
        "proximity",
        "attribute",
        "exact",
        "custom",
      ]).setSettings();

      await algoliaTask
          .waitTask()
          .timeout(const Duration(seconds: timeOutSecond))
          .catchError((onError) {
        if (onError is SocketException) {
          throw const AppException.noInternet();
        } else if (onError is TimeoutException) {
          throw const AppException.timeOut();
        } else {
          throw const AppException.unknown();
        }
      });
    }


    final customRanking = algoliaOutput.customRanking;

    if (customRanking != null && customRanking.isNotEmpty) {
      final AlgoliaTask algoliaTask = await algoliaIndexReference.settings
          .setCustomRanking(customRanking)
          .setSettings();

      await algoliaTask
          .waitTask()
          .timeout(const Duration(seconds: timeOutSecond))
          .catchError((onError) {
        if (onError is SocketException) {
          throw const AppException.noInternet();
        } else if (onError is TimeoutException) {
          throw const AppException.timeOut();
        } else {
          throw const AppException.unknown();
        }
      });
    }
  }
}

内容的提问来源于stack exchange,提问作者mario francois

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:10:23