Flutter文本索引插件text_indexing的使用

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

Flutter文本索引插件text_indexing的使用

本库提供了接口和实现类,用于构建和维护一个(位置,区域)倒排索引,适用于文档集合或corpus(见定义部分)。

性能

使用包含美国市场股票数据的数据集对TextIndexerInvertedIndex实现进行了基准测试。该数据集包含20,770个JSON文档,每个文档包含每只股票的基本信息,JSON数据文件大小为22MB。

索引构建时间

对于索引我们的样本数据集至243,700个术语和18,276个k-gram,使用InMemoryIndex与基于Hive的索引的时间如下:

倒排索引实现 总耗时 每文档耗时
InMemoryIndex ~15秒 0.68毫秒
基于Hive的索引 ~41分钟 112毫秒

在内存中构建索引比将其放入Hive箱(一种相对快速的本地存储选项)快165倍。

如果内存允许且文档集合较小,InMemoryIndex是明显赢家。特别是postings所需的内存可能使得其在较大文档集合中不实用。AsyncCallbackIndex类提供了灵活性,可以从不同的数据源访问三个索引哈希映射中的每一个,因此实现应用程序可以将dictionaryk-gram索引保持在内存中,而将postings放在本地存储中。或者,在内存缓存也可能为具有大量重复术语的语料库提供性能提升。

无论InvertedIndex实现如何,应用程序应避免在用户界面线程上运行TextIndexer以避免UI卡顿。

查询时间

创建了持久化索引后,我们对包含9个已知存在于样本数据中的术语的搜索短语进行了查询。查询需要多次往返于三个索引之间来匹配术语,计算逆文档词频等。从InMemoryIndex与基于Hive的索引检索数据的时间如下:

倒排索引实现 总耗时
InMemoryIndex ~22毫秒
基于Hive的索引 ~205毫秒

如预期,InMemoryIndex比基于Hive的索引更快,但在实际应用中,即使对于预测文本或自动更正应用,这种差异也可能是微不足道的。

使用

在您的Flutter项目的pubspec.yaml中添加text_indexing依赖。

dependencies:
  text_indexing: <最新版本>

在代码文件中添加text_indexing导入。

// 导入核心类
import 'package:text_indexing/text_indexing.dart';

// 如果需要,导入类型定义
import 'package:text_indexing/type_definitions.dart';

// 如果需要,导入扩展
import 'package:text_indexing/extensions.dart';

对于小集合,使用InMemoryIndex实例化一个TextIndexer(可选地传递空的DictionaryPostings哈希映射)。

调用TextIndexer.indexCollection方法将文档集合添加到索引中。

// 初始化一个用于JSON集合的内存索引,有两个索引字段
final myIndex = InMemoryIndex(
    zones: {'name': 1.0, 'description': 0.5},
    nGramRange: NGramRange(1, 2));

// 初始化一个`TextIndexer`,传入索引
final indexer = TextIndexer(index: myIndex);

// 索引JSON集合`documents`
await indexer.indexCollection(documents);

API

API公开了TextIndexer接口,用于为文档集合构建和维护InvertedIndex

为了最大化索引器的性能,API在嵌套的哈希映射中执行查找操作。

API包含了大量的样板代码,但我们旨在使代码尽可能可读、可扩展和可重用。

定义

以下是文档中使用的定义:

  • corpus - 文档的集合,为这些文档维护索引。
  • cosine similarity - 两个向量之间的相似性,测量为它们之间的余弦角度,即向量的点积除以其欧几里得长度的乘积。
  • character filter - 在分词前过滤文本中的字符。
  • Damerau–Levenshtein distance - 通过计算将一个词变为另一个词所需的最少操作数(插入、删除或替换单个字符,或交换两个相邻字符)来衡量两个词之间的编辑距离。
  • dictionary (in an index) - 将词(词汇)到其在corpus文档中出现频率的哈希映射。
  • document - corpus中的记录,具有唯一的标识符(docId),在corpus的主要键中,并包含一个或多个被索引的文本字段。
  • document frequency (dFt) - 包含术语的文档数量。
  • edit distance - 通过计算将一个字符串变为另一个字符串所需的最小操作数来衡量两个词的差异。
  • etymology - 词的历史形式研究,及其随时间演变的语义意义。
  • Flesch reading ease score - 通过句子长度和单词长度计算的可读性度量,范围在100分制上,分数越高,文档越容易理解。
  • Flesch-Kincaid grade level - 相对于美国学校年级的可读性度量,同样由句子长度和单词长度计算得出。
  • IETF language tag - 用于互联网上的语言标准化代码或标签。
  • index - 用于从corpus中的文档引用到term词汇表的倒排索引。
  • index-elimination - 从索引中选择包含在搜索短语中的术语的条目。
  • inverse document frequency (iDft) - 归一化的术语稀有性度量,定义为log(N / dft),其中N是索引中的总术语数。稀有术语的iDft较高,而常见术语的iDft可能较低。
  • Jaccard index - 测量有限样本集之间的相似性,定义为样本集交集大小除以样本集并集大小。
  • Map<String, dynamic> - JavaScript对象表示法,一种常见的数据持久化格式。
  • k-gram - 来自术语的任意k个连续字符的序列。k-gram可以以$开头,表示术语的开始,也可以以$结尾,表示术语的结束。castle的3-grams是{ $ca, cas, ast, stl, tle, le$ }。
  • lemma 或 lemmatizer - 词形还原过程将词的各种形态归并为一个项,以便作为单个项进行分析,由词的词典形式(词元)识别。
  • n-gram - 从给定文本或语音样本中提取的连续n个项目序列。项目可以是音素、音节、字母、单词或根据应用的碱基对。通常从文本或语音corpus中收集n-grams。当项目是单词时,n-grams也可能被称为shingles。
  • Natural language processing (NLP) - 语言学、计算机科学和人工智能的一个子领域,涉及计算机与人类语言之间的交互,尤其是编程计算机处理和分析大量自然语言数据。
  • Part-of-Speech (PoS) tagging - 任务是对一系列词中的每个词进行标记,指示其在给定序列中的词法句法类别。
  • Phonetic transcription - 通过符号表示语音声音(或电话)的视觉表示。最常见的类型是使用国际音标(IPA)的音标转写。
  • postings - 记录术语出现在哪些文档中的单独索引。在位置索引中,postings还记录每个术语在文本中的位置,以创建位置倒排索引。
  • postings list - 记录术语在文档中的位置的记录。术语的位置是指包含文档中所有术语的数组中术语的索引。在区域索引中,postings lists记录每个术语在文本的区域中的位置。
  • stem 或 stemmer - 通过减少词的词干、基本形式或根形式(通常是书面形式)来简化词的形态。
  • stopwords - 语言中常见的词,排除在索引之外。
  • term - 从corpus中索引的词或短语。术语可能与在corpus中实际使用的词不同,这取决于所使用的tokenizer
  • term filter - 从术语集合中过滤掉不需要的术语(例如停用词)、将复合术语分解为单独的术语和/或通过调用词干提取器和/或词形还原器来操纵术语。
  • term expansion - 查找具有类似拼写的术语(例如拼写纠正)或术语的同义词。
  • term frequency (Ft) - 术语在索引或索引对象中的频率。
  • term position - 在从corpus分词的有序术语数组中的术语零基索引。
  • text - 文档的可索引内容。
  • token - 经过tokenizer返回的文本源中的术语表示。token可能包括有关术语的信息,例如其在文本中的位置(术语位置)或出现频率(术语频率)。
  • token filter - 返回tokenizer输出的token子集。
  • tokenizer - 一个函数,返回来自文本的术语集合,应用了字符过滤器、术语过滤器、词干提取器和/或词形还原器。
  • vocabulary - 从corpus中索引的术语集合。
  • zone - 术语在文档中出现的字段或区域,用于参数化索引或在搜索结果评分和排名时,将更高的分数分配给在特定区域(例如文档的标题而不是正文)中包含术语的文档。

示例代码

以下是一个简单的例子,展示了如何使用TextIndexer.inMemorytextData数据集进行索引。

import 'package:text_indexing/src/_index.dart';

/// 四段文本用于测试。
///
/// 包括数字、货币、缩写、连字符和标识符
final textData = {
  'doc000': 'The Dow Jones rallied even as U.S. troops were put on alert amid '
      'the Ukraine crisis. Tesla stock fought back while Apple '
      'stock struggled. ',
  'doc001': '[TSLA.XNGS] Tesla\'s #TeslaMotor Stock Is Getting Hammered.',
  'doc002': 'Among the best EV stocks to buy and watch, Tesla '
      '(TSLA.XNGS) is pulling back from new highs after a failed breakout '
      'above a \$1,201.05 double-bottom entry. ',
  'doc003': 'Meanwhile, Peloton reportedly finds an activist investor knocking '
      'on its door after a major stock crash fueled by strong indications of '
      'mismanagement. In a scathing new letter released Monday, activist '
      'Tesla Capital is pushing for Peloton to fire CEO, Chairman and '
      'founder John Foley and explore a sale.'
};

/// 四段文本用于测试。
///
/// 包括数字、货币、缩写、连字符和标识符
final textData = {
  'doc000': 'The Dow Jones rallied even as U.S. troops were put on alert amid '
      'the Ukraine crisis. Tesla stock fought back while Apple '
      'stock struggled. ',
  'doc001': '[TSLA.XNGS] Tesla\'s #TeslaMotor Stock Is Getting Hammered.',
  'doc002': 'Among the best EV stocks to buy and watch, Tesla '
      '(TSLA.XNGS) is pulling back from new highs after a failed breakout '
      'above a \$1,201.05 double-bottom entry. ',
  'doc003': 'Meanwhile, Peloton reportedly finds an activist investor knocking '
      'on its door after a major stock crash fueled by strong indications of '
      'mismanagement. In a scathing new letter released Monday, activist '
      'Tesla Capital is pushing for Peloton to fire CEO, Chairman and '
      'founder John Foley and explore a sale.'
};

/// 用于演示字段持久化索引的Map<String, dynamic>数据。
final jsonData = {
  'ee1760a1-a259-50dc-b11d-8baf34d7d1c5': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FTSLA%3AXNGS.png?alt=media&token=c365db47-9482-4237-9267-82f72854d161',
    'description':
        'A 20-for-1 stock split gave a nice short-term boost to Amazon (AMZN) - Get Amazon.com Inc. Report in late May and in early June, while Alphabet (GOOGL) - Get Alphabet Inc. Report (GOOG) - Get Alphabet Inc. Report has a planned 20-for-1 stock split for next month. Tesla&nbsp; (TSLA) - Get Tesla Inc. Report&nbsp;is also waiting on shareholder approval for a 3-for-1 stock split. ',
    'entityType': 'NewsItem',
    'hashTags': ['#Tesla'],
    'id': 'ee1760a1-a259-50dc-b11d-8baf34d7d1c5',
    'itemGuid':
        'trading-shopify-stock-ahead-of-10-for-1-stock-split-technical-analysis-june-2022?puc=yahoo&cm_ven=YAHOO&yptr=yahoo',
    'linkUrl':
        'https://www.thestreet.com/investing/trading-shopify-stock-ahead-of-10-for-1-stock-split-technical-analysis-june-2022?puc=yahoo&cm_ven=YAHOO&yptr=yahoo',
    'locale': 'Locale.en_US',
    'name': 'Shopify Stock Split What the Charts Say Ahead of 10-for-1 Split',
    'publicationDate': '2022-06-28T17:44:00.000Z',
    'publisher': {
      'linkUrl': 'http://www.thestreet.com/',
      'title': 'TheStreet com'
    },
    'timestamp': 1656464362162
  },
  'ee1d9610-b902-53e6-8264-840bd403365b': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FO%3AXNYS.png?alt=media&token=15b5e8fe-bec2-4711-b0f7-e5a631287e9e',
    'description': 'OR',
    'entityType': 'NewsItem',
    'hashTags': ['#RealtyIncome'],
    'id': 'ee1d9610-b902-53e6-8264-840bd403365b',
    'itemGuid': 'auddev&yptr=yahoo',
    'linkUrl':
        'https://www.ft.com/cms/s/0ea7bcc1-d3a6-4897-8da3-98798c3be487,s01=1.html?ftcamp=traffic/partner/feed_headline/us_yahoo/auddev&yptr=yahoo',
    'locale': 'Locale.en_US',
    'name': 'History says US stock market has further to fall',
    'publicationDate': '2022-06-25T12:35:45.000Z',
    'publisher': {'linkUrl': 'http://ft.com/', 'title': 'Financial Times'},
    'timestamp': 1656193158270
  },
  'ef3b0cb6-0297-502b-bd77-283246bc0014': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FJPM-C%3AXNYS.png?alt=media&token=deba8c6d-019e-4d49-9faa-d641a3cf1986',
    'description':
        'JPMorgan Sees ‘Stratospheric’ \$380 Oil on Worst-Case Russian Cut',
    'entityType': 'NewsItem',
    'hashTags': ['#JPMorganChase'],
    'id': 'ef3b0cb6-0297-502b-bd77-283246bc0014',
    'itemGuid': 'germany-risks-cascade-utility-failures-194853753.html',
    'linkUrl':
        'https://finance.yahoo.com/news/germany-risks-cascade-utility-failures-194853753.html',
    'locale': 'Locale.en_US',
    'name': 'Germany Risks a Cascade of Utility Failures Economy Chief Says',
    'publicationDate': '2022-07-02T19:48:53.000Z',
    'publisher': {
      'linkUrl': 'https://www.bloomberg.com/',
      'title': 'Bloomberg'
    },
    'timestamp': 1656802194091
  },
  'f1064cca-bf6d-5689-900b-ecb8769fe30b': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FINTC%3AXNGS.png?alt=media&token=cfefaa0a-7f06-42f8-a316-954ded1fd703',
    'description':
        'Under CEO Pat Gelsinger, Intel has committed to massively increasing its capital spending investments by tens of billions of dollars. But with a rapidly slowing global economy, repeated product delays, rising competitive threats, and political uncertainty, it might need more help to fund its ambitions. One good place to find it would be Intel (ticker: INTC) generous dividend payout. While the chip maker has paid a consistent dividend for three decades straight, it needs to do whatever it takes to shore up its future—up to and including cutting its dividend. Under CEO Pat Gelsinger, Intel has committed to massively increasing its capital spending investments by tens of billions of dollars.',
    'entityType': 'NewsItem',
    'hashTags': ['#Intel'],
    'id': 'f1064cca-bf6d-5689-900b-ecb8769fe30b',
    'itemGuid':
        'intel-stock-dividend-future-51656450364?siteid=yhoof2&yptr=yahoo',
    'linkUrl':
        'https://www.barrons.com/articles/intel-stock-dividend-future-51656450364?siteid=yhoof2&yptr=yahoo',
    'locale': 'Locale.en_US',
    'name':
        'Intel Should Slash Its Dividend The Chip Maker s Future May Depend on It',
    'publicationDate': '2022-06-29T12:00:00.000Z',
    'publisher': {'linkUrl': 'http://www.barrons.com/', 'title': 'Barrons com'},
    'timestamp': 1656540522708
  },
  'f2fa8eea-6259-5c83-8865-e0b7f80e691d': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FINTC%3AXNGS.png?alt=media&token=cfefaa0a-7f06-42f8-a316-954ded1fd703',
    'description':
        'Consumers are being hit by the run-up in gasoline, diesel and other oil products, Mike Muller, head of Asia at Vitol Group, said Sunday on a podcast produced by Dubai-based Gulf Intelligence.',
    'hashTags': ['#Intel', '#JPMorganChase'],
    'id': 'f2fa8eea-6259-5c83-8865-e0b7f80e691d',
    'itemGuid': 'surging-fuel-costs-causing-demand-100930872.html',
    'linkUrl':
        'https://finance.yahoo.com/news/surging-fuel-costs-causing-demand-100930872.html',
    'locale': 'Locale.en_US',
    'name': 'Surging Fuel Costs Are Causing Demand Destruction Says Vitol',
    'publicationDate': '2022-07-03T10:09:30.000Z',
    'publisher': {
      'linkUrl': 'https://www.bloomberg.com/',
      'title': 'Bloomberg'
    },
    'timestamp': 1656881075901
  },
  'f6ee5edf-094f-5892-9b37-71b8f2e90d03': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FAAPL%3AXNGS.png?alt=media&token=fb44cde6-4552-42e7-b1b0-7eddc92b1dfc',
    'description':
        'The Dow Jones Industrial Average rallied out of the red after the latest Fed minutes were released. EV stock Rivian (RIVN) soared on guidance even as Tesla (TSLA) fell. Microsoft (MSFT) and Apple (AAPL) were among the top blue chips.',
    'entityType': 'NewsItem',
    'hashTags': ['#Apple', '#Tesla'],
    'id': 'f6ee5edf-094f-5892-9b37-71b8f2e90d03',
    'itemGuid': '?src=A00220&yptr=yahoo',
    'linkUrl':
        'https://www.investors.com/market-trend/stock-market-today/dow-jones-rallies-as-fed-minutes-reveal-this-jerome-powell-ev-stock-explodes-on-guidance-tesla-stock-apple-stock-pops/?src=A00220&yptr=yahoo',
    'locale': 'Locale.en_US',
    'name':
        'Dow Jones Rallies As Fed Minutes Reveal This EV Stock Explodes On Guidance Apple Stock Vaults',
    'publicationDate': '2022-07-06T19:15:45.000Z',
    'publisher': {
      'linkUrl': 'http://www.investors.com/',
      'title': "Investor's Business Daily"
    },
    'timestamp': 1657158311943
  },
  'f83c0c39-8cc3-5b0e-91de-61e829ea65dc': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FXOM%3AXNYS.png?alt=media&token=c94499b0-5937-47ea-8f89-94d65d3ed065',
    'description':
        'Sell Exxon Mobil and other energy stocks before these headwinds hit prices once again: ',
    'entityType': 'NewsItem',
    'hashTags': ['#ExxonMobil'],
    'id': 'f83c0c39-8cc3-5b0e-91de-61e829ea65dc',
    'itemGuid':
        'sell-exxon-mobil-and-other-energy-stocks-before-these-headwinds-once-again-hit-prices-11656527286?siteid=yhoof2&yptr=yahoo',
    'linkUrl':
        'https://www.marketwatch.com/story/sell-exxon-mobil-and-other-energy-stocks-before-these-headwinds-once-again-hit-prices-11656527286?siteid=yhoof2&yptr=yahoo',
    'locale': 'Locale.en_US',
    'name':
        'Sell Exxon Mobil and other energy stocks before these headwinds hit prices once again',
    'publicationDate': '2022-06-29T18:28:00.000Z',
    'publisher': {
      'linkUrl': 'http://www.marketwatch.com/',
      'title': 'MarketWatch'
    },
    'timestamp': 1656630576652
  },
  'fa2b9c9e-096e-5e27-917a-26badeabff83': {
    'avatarImageUrl':
        'https://firebasestorage.googleapis.com/v0/b/buysellhold-322d1.appspot.com/o/logos%2FTSLA%3AXNGS.png?alt=media&token=c365db47-9482-4237-9267-82f72854d161',
    'description':
        'Tesla Pauses Plants After Ending Shaky Quarter With a Production Milestone',
    'entityType': 'NewsItem',
    'hashTags': ['#Tesla'],
    'id': 'fa2b9c9e-096e-5e27-917a-26badeabff83',
    'itemGuid': 'natural-gas-soars-700-becoming-040106114.html',
    'linkUrl':
        'https://finance.yahoo.com/news/natural-gas-soars-700-becoming-040106114.html',
    'locale': 'Locale.en_US',
    'name': 'Natural Gas Soars 700% Becoming Driving Force in the New Cold War',
    'publicationDate': '2022-07-05T04:01:06.000Z',
    'publisher': {
      'linkUrl': 'https://www.bloomberg.com/',
      'title': 'Bloomberg'
    },
    'timestamp': 1657002625523
  }
};

主要代码解析

/// 初始化一个用于JSON集合的内存索引,有两个索引字段
final myIndex = InMemoryIndex(
    zones: {'name': 1.0, 'description': 0.5},
    nGramRange: NGramRange(1, 2));

// 初始化一个`TextIndexer`,传入索引
final indexer = TextIndexer(index: myIndex);

// 索引JSON集合`documents`
await indexer.indexCollection(documents);

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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用text_indexing插件的示例代码。text_indexing插件允许你对文本进行索引和搜索,这对于需要高效文本搜索功能的应用非常有用。

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

dependencies:
  flutter:
    sdk: flutter
  text_indexing: ^最新版本号 # 替换为当前最新版本号

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

接下来是一个简单的示例代码,展示如何使用text_indexing插件对文本进行索引和搜索:

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

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

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

class _MyAppState extends State<MyApp> {
  final TextIndexer _indexer = TextIndexer();
  List<String> _indexedDocuments = [];
  String _searchQuery = '';
  List<SearchResult> _searchResults = [];

  @override
  void initState() {
    super.initState();
    // 初始化一些文档
    _indexedDocuments = [
      'Flutter is an open-source UI software development kit created by Google.',
      'It is used to develop applications for Android, iOS, Linux, macOS, Windows, and the web from a single codebase.',
      'Flutter’s hot reload helps you quickly and easily experiment, build UIs, add features, and fix bugs faster.',
    ];

    // 对文档进行索引
    _indexer.addDocuments(_indexedDocuments);
  }

  void _performSearch() {
    setState(() {
      _searchResults = _indexer.search(_searchQuery);
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Text Indexing Demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              TextField(
                decoration: InputDecoration(labelText: 'Search Query'),
                onChanged: (value) {
                  _searchQuery = value;
                  _performSearch();
                },
              ),
              SizedBox(height: 16),
              Expanded(
                child: _searchResults.isEmpty
                    ? Text('No results found.')
                    : ListView.builder(
                        itemCount: _searchResults.length,
                        itemBuilder: (context, index) {
                          final result = _searchResults[index];
                          return ListTile(
                            title: Text('Document: ${result.documentIndex + 1}\nScore: ${result.score}'),
                            subtitle: Text('Snippet: ${result.snippet}'),
                          );
                        },
                      ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

代码说明:

  1. 依赖导入:首先,确保在pubspec.yaml中添加了text_indexing依赖。
  2. 状态管理:使用StatefulWidget来管理应用的状态,包括索引的文档、搜索查询和搜索结果。
  3. 初始化索引:在initState方法中,初始化一些文档并使用TextIndexeraddDocuments方法将它们添加到索引中。
  4. 搜索功能:在TextFieldonChanged回调中,每当搜索查询改变时,调用_performSearch方法进行搜索。
  5. 显示结果:使用ListView.builder来显示搜索结果,包括文档索引、得分和摘要。

这个示例展示了如何使用text_indexing插件对文本进行索引和实时搜索。你可以根据实际需求对代码进行扩展和修改。

回到顶部