smartSearchWithScores method

Future<List<SmartSearchResult<T>>> smartSearchWithScores({
  1. required String query,
  2. required Map<String, List<String>> searchFieldsMap,
  3. required Map<String, dynamic> toJson(
    1. T
    ),
  4. Map<String, double> fieldWeights = const {},
  5. double minScore = 0.3,
  6. int limit = 10,
  7. bool useDamerauLevenshtein = true,
  8. bool useNGram = true,
  9. bool useIsolate = true,
  10. bool debug = false,
})

Performs search and returns results with scores.

Returns SmartSearchResult objects that include both the item and its score, useful when you need to display or filter by relevance scores.

Note: This recalculates scores after filtering, so it's slightly less efficient than smartSearchDynamicDetailedExtension but provides score access.

See smartSearchDynamicDetailedExtension for parameter documentation.

Example:

final results = await products.smartSearchWithScores<Product>(
  query: 'samsung',
  searchFieldsMap: {'name': ['nameEn']},
  toJson: (p) => p.toJson(),
);
for (final result in results) {
  print('${result.item.nameEn}: ${result.score}');
}

Implementation

Future<List<SmartSearchResult<T>>> smartSearchWithScores({
  required String query,
  required Map<String, List<String>> searchFieldsMap,
  required Map<String, dynamic> Function(T) toJson,
  Map<String, double> fieldWeights = const {},
  double minScore = 0.3,
  int limit = 10,
  bool useDamerauLevenshtein = true,
  bool useNGram = true,
  bool useIsolate = true,
  bool debug = false,
}) async {
  // Get items first
  final items = await smartSearchDynamicDetailedExtension(
    query: query,
    searchFieldsMap: searchFieldsMap,
    toJson: toJson,
    fieldWeights: fieldWeights,
    minScore: minScore,
    limit: limit,
    useDamerauLevenshtein: useDamerauLevenshtein,
    useNGram: useNGram,
    useIsolate: useIsolate,
    debug: false, // Disable debug to avoid duplicate output
  );

  // Recalculate scores for SearchResult objects
  final queryWordGroups = EnhancedSmartSearch.groupQueryWordsByOriginal(query);
  final results = <SmartSearchResult<T>>[];

  for (final item in items) {
    final itemJson = toJson(item);
    double totalScore = 0.0;
    double totalWeight = 0.0;

    searchFieldsMap.forEach((fieldName, subFields) {
      final weight = fieldWeights[fieldName] ?? 1.0;
      final fieldWords = <String>[];

      for (final subField in subFields) {
        if (!itemJson.containsKey(subField)) continue;
        final value = itemJson[subField];
        if (value is List) {
          for (final v in value) {
            fieldWords.addAll(EnhancedSmartSearch.splitWords(v.toString()));
          }
        } else if (value != null) {
          fieldWords.addAll(EnhancedSmartSearch.splitWords(value.toString()));
        }
      }

      final fieldScore = EnhancedSmartSearch.itemScore(
        fieldWords,
        queryWordGroups,
        useDamerauLevenshtein,
        useNGram,
      );

      totalScore += fieldScore * weight;
      totalWeight += weight;
    });

    final score = totalWeight > 0 ? totalScore / totalWeight : 0.0;
    results.add(SmartSearchResult<T>(item, score));
  }

  // Sort by score descending
  results.sort((a, b) => b.score.compareTo(a.score));

  return results;
}