Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Facet search #344

Merged
merged 4 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions lib/meilisearch.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
library meilisearch;

export 'src/client.dart';
export 'src/index.dart';
export 'src/settings/_exports.dart';
export 'src/facet_stat.dart';
export 'src/match_position.dart';
export 'src/searchable.dart';
export 'src/multi_search_result.dart';
export 'src/query_parameters/multi_search_query.dart';
export 'src/query_parameters/index_search_query.dart';
export 'src/filter_builder/_exports.dart';
export 'src/results/_exports.dart';
export 'src/query_parameters/_exports.dart';
export 'src/matching_strategy_enum.dart';
export 'src/key.dart';
export 'src/filter_builder/_exports.dart';
export 'src/client.dart';
export 'src/index.dart';
export 'src/exception.dart';
export 'src/task.dart';
export 'src/swap_index.dart';
export 'src/facade.dart';
12 changes: 1 addition & 11 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import 'package:meilisearch/meilisearch.dart';
import 'package:dio/dio.dart';
import 'annotations.dart';
import 'query_parameters/_exports.dart';
import 'result.dart';
import 'swap_index.dart';
import 'tasks_results.dart';
import 'task.dart';
import 'tenant_token.dart';

import 'multi_search_result.dart';
import 'http_request.dart';
import 'index.dart';

import 'key.dart';
import 'stats.dart' show AllStats;

class MeiliSearchClient {
MeiliSearchClient(
Expand Down
2 changes: 1 addition & 1 deletion lib/src/http_request.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:dio/dio.dart';
import 'package:meilisearch/src/version.dart';
import 'version.dart';

import 'exception.dart';

Expand Down
13 changes: 10 additions & 3 deletions lib/src/index.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:meilisearch/meilisearch.dart';
import 'result.dart';
import 'tasks_results.dart';
import 'annotations.dart';
import 'package:collection/collection.dart';
import 'http_request.dart';
import 'stats.dart' show IndexStats;

const _ndjsonContentType = 'application/x-ndjson';
const _csvContentType = 'text/csv';
Expand Down Expand Up @@ -104,6 +102,15 @@ class MeiliSearchIndex {
return Searcheable.createSearchResult(response.data!, indexUid: uid);
}

@RequiredMeiliServerVersion('1.3.0')
Future<FacetSearchResult> facetSearch(FacetSearchQuery query) async {
final response = await http.postMethod<Map<String, Object?>>(
'/indexes/$uid/facet-search',
data: query.toSparseMap(),
);
return FacetSearchResult.fromMap(response.data!);
}

//
// Document endpoints
//
Expand Down
2 changes: 2 additions & 0 deletions lib/src/query_parameters/_exports.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ export 'index_search_query.dart';
export 'search_query.dart';
export 'multi_search_query.dart';
export 'delete_documents_query.dart';
export 'facet_search_query.dart';
export 'swap_index.dart';
2 changes: 1 addition & 1 deletion lib/src/query_parameters/cancel_tasks_query.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:meilisearch/src/query_parameters/queryable.dart';
import 'queryable.dart';

class CancelTasksQuery extends Queryable {
final DateTime? beforeEnqueuedAt;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/query_parameters/delete_tasks_query.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:meilisearch/src/query_parameters/queryable.dart';
import 'queryable.dart';

class DeleteTasksQuery extends Queryable {
final DateTime? beforeEnqueuedAt;
Expand Down
42 changes: 42 additions & 0 deletions lib/src/query_parameters/facet_search_query.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import '../annotations.dart';
import 'search_query.dart';

@RequiredMeiliServerVersion('1.3.0')
class FacetSearchQuery extends SearchQuery {
const FacetSearchQuery({
required this.facetName,
this.facetQuery = '',
this.q = '',
//Per spec, only filter and matchingStrategy are shared with the parent SearchQuery

/// Additional search parameter.
///
/// If additional search parameters are set, the method will return facet values that both:
/// - Match the face query
/// - Are contained in the records matching the additional search parameters
super.filter,
super.filterExpression,
super.matchingStrategy,
});

final String facetName;

final String facetQuery;

/// Additional search parameter.
///
/// If additional search parameters are set, the method will return facet values that both:
/// - Match the face query
/// - Are contained in the records matching the additional search parameters
final String q;

@override
Map<String, Object?> buildMap() {
return {
'facetName': facetName,
'facetQuery': facetQuery,
'q': q,
...super.buildMap(),
};
}
}
2 changes: 1 addition & 1 deletion lib/src/query_parameters/index_search_query.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../annotations.dart';
import '../filter_builder/_exports.dart';
import '../matching_strategy_enum.dart';
import '../results/matching_strategy_enum.dart';
import 'search_query.dart';

@RequiredMeiliServerVersion('1.1.0')
Expand Down
2 changes: 1 addition & 1 deletion lib/src/query_parameters/indexes_query.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:meilisearch/src/query_parameters/queryable.dart';
import 'queryable.dart';

class IndexesQuery extends Queryable {
final int? offset;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/query_parameters/keys_query.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:meilisearch/src/query_parameters/queryable.dart';
import 'queryable.dart';

class KeysQuery extends Queryable {
final int? offset;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/query_parameters/multi_search_query.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:meilisearch/src/query_parameters/queryable.dart';
import 'queryable.dart';

import '../annotations.dart';
import 'index_search_query.dart';
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion lib/src/query_parameters/tasks_query.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:meilisearch/src/query_parameters/queryable.dart';
import 'queryable.dart';

class TasksQuery extends Queryable {
final int? from;
Expand Down
14 changes: 14 additions & 0 deletions lib/src/results/_exports.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export 'multi_search_result.dart';
export 'searchable.dart';
export 'tasks_results.dart';
export 'result.dart';
export 'facet_search_result.dart';
export 'facet_hit.dart';
export 'key.dart';
export 'task.dart';
export 'task_error.dart';
export 'match_position.dart';
export 'matching_strategy_enum.dart';
export 'index_stats.dart';
export 'all_stats.dart';
export 'facet_stat.dart';
19 changes: 1 addition & 18 deletions lib/src/stats.dart → lib/src/results/all_stats.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,4 @@
class IndexStats {
IndexStats({
this.numberOfDocuments,
this.isIndexing,
this.fieldsDistribution,
});

final int? numberOfDocuments;
final bool? isIndexing;
final Map<String, int>? fieldsDistribution;

factory IndexStats.fromMap(Map<String, Object?> map) => IndexStats(
numberOfDocuments: map['numberOfDocuments'] as int?,
isIndexing: map['isIndexing'] as bool?,
fieldsDistribution:
(map['fieldsDistribution'] as Map?)?.cast<String, int>(),
);
}
import 'index_stats.dart';

class AllStats {
AllStats({
Expand Down
19 changes: 19 additions & 0 deletions lib/src/results/facet_hit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import '../annotations.dart';

@RequiredMeiliServerVersion('1.3.0')
class FacetHit {
final String value;
final int count;

const FacetHit({
required this.value,
required this.count,
});

factory FacetHit.fromMap(Map<String, dynamic> map) {
return FacetHit(
value: map['value'] as String,
count: map['count'] as int,
);
}
}
29 changes: 29 additions & 0 deletions lib/src/results/facet_search_result.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import '../annotations.dart';
import 'facet_hit.dart';

@RequiredMeiliServerVersion('1.3.0')
class FacetSearchResult {
final List<FacetHit> facetHits;
final String facetQuery;
final int processingTimeMs;

const FacetSearchResult({
required this.facetHits,
required this.facetQuery,
required this.processingTimeMs,
});

factory FacetSearchResult.fromMap(Map<String, dynamic> map) {
return FacetSearchResult(
facetHits: List<FacetHit>.from(
(map['facetHits'] as List?)
?.cast<Map<String, dynamic>>()
.map(FacetHit.fromMap)
.toList() ??
[],
),
facetQuery: map['facetQuery'] as String,
processingTimeMs: map['processingTimeMs'] as int,
);
}
}
42 changes: 21 additions & 21 deletions lib/src/facet_stat.dart → lib/src/results/facet_stat.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
///When using the facets parameter, the distributed facets that contain some numeric values are displayed in a facetStats object that contains, per facet, the numeric min and max values of the hits returned by the search query.
///If none of the hits returned by the search query have a numeric value for a facet, this facet is not part of the facetStats object.
class FacetStat {
///The minimum value for the numerical facet being distributed.
final num min;
///The maximum value for the numerical facet being distributed.
final num max;
const FacetStat({
required this.min,
required this.max,
});
factory FacetStat.fromMap(Map<String, Object?> src) {
return FacetStat(
min: src['min'] as num,
max: src['max'] as num,
);
}
}
///When using the facets parameter, the distributed facets that contain some numeric values are displayed in a facetStats object that contains, per facet, the numeric min and max values of the hits returned by the search query.
///If none of the hits returned by the search query have a numeric value for a facet, this facet is not part of the facetStats object.
class FacetStat {
///The minimum value for the numerical facet being distributed.
final num min;

///The maximum value for the numerical facet being distributed.
final num max;

const FacetStat({
required this.min,
required this.max,
});

factory FacetStat.fromMap(Map<String, Object?> src) {
return FacetStat(
min: src['min'] as num,
max: src['max'] as num,
);
}
}
18 changes: 18 additions & 0 deletions lib/src/results/index_stats.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class IndexStats {
IndexStats({
this.numberOfDocuments,
this.isIndexing,
this.fieldsDistribution,
});

final int? numberOfDocuments;
final bool? isIndexing;
final Map<String, int>? fieldsDistribution;

factory IndexStats.fromMap(Map<String, Object?> map) => IndexStats(
numberOfDocuments: map['numberOfDocuments'] as int?,
isIndexing: map['isIndexing'] as bool?,
fieldsDistribution:
(map['fieldsDistribution'] as Map?)?.cast<String, int>(),
);
}
File renamed without changes.
32 changes: 16 additions & 16 deletions lib/src/match_position.dart → lib/src/results/match_position.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
class MatchPosition {
final int start;
final int length;
const MatchPosition({
required this.start,
required this.length,
});
factory MatchPosition.fromMap(Map<String, dynamic> map) {
return MatchPosition(
start: map['start'] as int,
length: map['length'] as int,
);
}
}
class MatchPosition {
final int start;
final int length;

const MatchPosition({
required this.start,
required this.length,
});

factory MatchPosition.fromMap(Map<String, dynamic> map) {
return MatchPosition(
start: map['start'] as int,
length: map['length'] as int,
);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import 'searchable.dart';
class MultiSearchResult {
final List<Searcheable<Map<String, Object?>>> results;
const MultiSearchResult({
required this.results,
});
factory MultiSearchResult.fromMap(Map<String, Object?> json) {
final list = json['results'] as List<Object?>;
final parsed = list
.cast<Map<String, Object?>>()
.map((e) => Searcheable.createSearchResult(e));
return MultiSearchResult(results: parsed.toList());
}
}
import 'searchable.dart';

class MultiSearchResult {
final List<Searcheable<Map<String, Object?>>> results;

const MultiSearchResult({
required this.results,
});

factory MultiSearchResult.fromMap(Map<String, Object?> json) {
final list = json['results'] as List<Object?>;
final parsed = list
.cast<Map<String, Object?>>()
.map((e) => Searcheable.createSearchResult(e));

return MultiSearchResult(results: parsed.toList());
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading