Flutter全文搜索插件elastic_app_search的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter全文搜索插件elastic_app_search的使用

简介

elastic_app_search 是一个用于在Flutter应用中集成Elastic App Search服务的包。它提供了一个简单的API,可以轻松地进行查询并处理结果。要使用此服务,您需要有一个活跃的Elastic部署。

Elastic

⚠️ 注意: 使用此服务前,请确保您已经在 Elastic Cloud 上拥有一个有效的部署。

快速开始

初始化ElasticAppSearch实例

在执行任何操作之前,您需要创建一个ElasticAppSearch实例:

final service = ElasticAppSearch(
  endPoint: "https://your-endpoint-url", 
  searchKey: "your-search-key",
);

提示: endPointsearchKey 可以在您的Elastic部署中的“App Search”->“Credentials”页面找到。

创建引擎实例

所有查询都必须发送到一个引擎。创建引擎实例非常简单:

final engine = service.engine("engine_name");

执行查询

接下来,您可以创建一个查询,并添加各种过滤器和选项来细化搜索结果:

ElasticResponse response = await engine
  .query("mountains")
  .filter("states", isEqualTo: "California")
  .filter("world_heritage_site", isEqualTo: true)
  .resultField("title")
  .resultField("description", snippetSize: 140)
  .page(1, size: 50)
  .get();

上述代码将搜索包含“mountains”的文档,同时根据特定条件(如位置在加利福尼亚州且为世界遗产)进行筛选,并仅返回标题及描述字段的部分内容。

完整示例:国家公园搜索应用

下面是一个完整的例子,展示了如何构建一个带有实时搜索、过滤功能的应用程序。该应用程序允许用户通过输入关键字来查找国家公园,并可以通过侧边栏选择不同的过滤条件来进一步缩小搜索范围。

主要功能

  • 搜索框支持动态查询。
  • 弹出菜单允许用户按是否是世界遗产地筛选公园。
  • 显示地图上的距离范围。

示例代码

import 'package:flutter/material.dart';
import 'package:elastic_app_search/elastic_app_search.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'National Parks Search',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ParkSearchPage(),
    );
  }
}

class ParkSearchPage extends StatefulWidget {
  const ParkSearchPage({super.key});

  @override
  State<ParkSearchPage> createState() => _ParkSearchPageState();
}

class _ParkSearchPageState extends State<ParkSearchPage> {
  final TextEditingController _controller = TextEditingController();
  List<Map<String, dynamic>> _results = [];
  bool _isLoading = false;

  Future<void> _performSearch(String query) async {
    setState(() {
      _isLoading = true;
    });

    try {
      final service = ElasticAppSearch(
        endPoint: "https://host-2376rb.api.swiftype.com",
        searchKey: "search-371auk61r2bwqtdzocdgutmg",
      );

      final response = await service
          .engine("search-ui-examples")
          .query(query)
          .filter("states", isEqualTo: "California")
          .filter("world_heritage_site", isEqualTo: true)
          .resultField("title")
          .resultField("description", snippetSize: 140)
          .page(1, size: 50)
          .get();

      setState(() {
        _results = response.results.map((result) => result.data!).toList();
      });
    } catch (e) {
      print('Error performing search: $e');
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  void initState() {
    super.initState();
    _controller.addListener(() {
      if (_controller.text.isNotEmpty && _controller.text.length >= 3) {
        _performSearch(_controller.text);
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('National Parks'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              controller: _controller,
              decoration: const InputDecoration(
                labelText: 'Search parks...',
                border: OutlineInputBorder(),
              ),
            ),
          ),
          Expanded(
            child: _isLoading
                ? const Center(child: CircularProgressIndicator())
                : ListView.builder(
                    itemCount: _results.length,
                    itemBuilder: (context, index) {
                      final park = _results[index];
                      return ListTile(
                        title: Text(park['title']),
                        subtitle: Text(park['description']),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }
}

这个例子演示了如何结合文本输入框与elastic_app_search库一起工作,实现基本的搜索功能。实际应用中还可以扩展更多特性,比如地理位置筛选、分页加载等。希望这能帮助您更好地理解和使用elastic_app_search插件!


更多关于Flutter全文搜索插件elastic_app_search的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter全文搜索插件elastic_app_search的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用elastic_app_search插件来实现全文搜索功能的代码案例。这个插件允许你与Elastic App Search服务进行交互,从而在你的应用中实现强大的搜索功能。

首先,确保你已经在pubspec.yaml文件中添加了elastic_app_search依赖:

dependencies:
  flutter:
    sdk: flutter
  elastic_app_search: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你需要配置Elastic App Search的客户端。以下是一个完整的示例,包括初始化客户端、执行搜索请求并处理结果。

import 'package:flutter/material.dart';
import 'package:elastic_app_search/elastic_app_search.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late ElasticAppSearchClient client;
  late Future<SearchResponse> searchFuture;
  String searchQuery = '';

  @override
  void initState() {
    super.initState();

    // 替换为你的Elastic App Search的API密钥、引擎名称和私有密钥
    final String apiKey = '你的API密钥';
    final String engineName = '你的引擎名称';
    final String privateKey = '你的私有密钥';

    client = ElasticAppSearchClient(
      apiKey: apiKey,
      engineName: engineName,
      searchKey: privateKey,
      endpoint: 'https://你的Elastic App Search实例URL.elastic-cloud.com/api/as/v1',
    );

    // 初始化搜索Future,这里用一个空查询来初始化
    searchFuture = _performSearch(searchQuery);
  }

  Future<SearchResponse> _performSearch(String query) async {
    try {
      final response = await client.search(query: query);
      return response;
    } catch (e) {
      // 处理错误,例如网络错误或API限制
      print('Search error: $e');
      throw e;
    }
  }

  void _onSearchQueryChanged(String newValue) {
    setState(() {
      searchQuery = newValue;
      searchFuture = _performSearch(newValue);
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Elastic App Search Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextField(
                decoration: InputDecoration(
                  labelText: 'Search',
                  suffixIcon: IconButton(
                    icon: Icon(Icons.clear),
                    onPressed: () {
                      _onSearchQueryChanged('');
                    },
                  ),
                ),
                onChanged: _onSearchQueryChanged,
              ),
              SizedBox(height: 16.0),
              Expanded(
                child: FutureBuilder<SearchResponse>(
                  future: searchFuture,
                  builder: (context, snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return Center(child: CircularProgressIndicator());
                    } else if (snapshot.hasError) {
                      return Center(child: Text('Error: ${snapshot.error}'));
                    } else if (snapshot.hasData) {
                      final results = snapshot.data?.results ?? [];
                      return ListView.builder(
                        itemCount: results.length,
                        itemBuilder: (context, index) {
                          final result = results[index];
                          return ListTile(
                            title: Text(result['title']),
                            subtitle: Text(result['_source']['content'].substring(0, 50) + '...'),
                          );
                        },
                      );
                    } else {
                      return Center(child: Text('No results'));
                    }
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个Flutter应用,其中包括一个搜索栏和一个显示搜索结果的列表。用户输入查询后,应用会调用Elastic App Search API并显示返回的结果。

注意:

  • 你需要替换你的API密钥你的引擎名称你的私有密钥你的Elastic App Search实例URL为实际的Elastic App Search服务信息。
  • 这个示例假设你的文档有一个title字段和一个content字段,你可能需要根据你的实际数据结构调整显示逻辑。

这个代码案例提供了一个基础框架,你可以根据具体需求进行扩展和优化。

回到顶部