【问题标题】:Storing words in a text在文本中存储单词
【发布时间】:2020-05-15 04:53:45
【问题描述】:

我正在使用 Rails 和 Postgresql 构建一个学习语言的应用程序。

文本被上传。文本的长度会有所不同,但我们假设它们的长度为 100-3000 字。

在上传时,每个文本位置都被转换为一个“标记”,表示该位置的单词信息(基本单词、名词/动词/形容词/等、语法标签、定义 ID)。

点击文本中的一个词时,我需要在数据库中查找(并显示)所有其他文本,这些文本与点击的词具有相同的属性(base_word、词性、标签)。

最简单和最相关的方法是在表TextWord 之间连接表TextWord。每个text_word 将代表文本中的一个位置,并包含text_idword_idgrammar_tagsstart_indexend_index

但是,如果文本包含 100-3000 个单词,这意味着每个文本对象有 100-3000 个条目。

这很疯狂吗?昂贵的?这会导致什么问题?

有没有更好的办法?

我不能使用 Postgres 全文搜索,因为例如,如果我在“我离开纳什维尔”中单击“左”,我不希望“在灯下左转”出现。我只想要“离开”作为动词,以及其他形式的“离开”作为动词。此外,我可能只想要具有特定定义 ID 的“左”(例如,“左”用作“政党”,而不是“右的对立面”)。

我能想到的另一个选择是在文本对象上存储一个 JSON,将标记作为一个大的 散列散列,或散列数组(无论哪种方式)。 Postgresql 有办法搜索这种嵌套的数据结构吗?

第三个选项是使用与选项 2 相同的 JSON(存储文本中的所有位置),以及每个单词对象/定义对象/语法对象上的第二个 json(存储所有文本中的所有位置,其中该对象出现)。但是,这似乎比连接表占用更多的存储空间,我不确定它是否会带来任何切实的好处。

任何建议将不胜感激。

谢谢, 迈克尔。

【问题讨论】:

  • 为什么要重新发明轮子?使用 PostgreSQL 全文搜索。
  • 因为如果我点击“我离开纳什维尔”中的“左”,我不希望出现“左转”(left => 名词)。它们需要在基本词/词性级别链接。我只想要动词“离开”(“离开”,还有“离开”、“离开”)。另外,我最终可能只想要那些标记为特定定义_id的。
  • 换句话说(不是双关语),我需要通过附加到每个位置的特定属性进行搜索,而不仅仅是直接的文本匹配。我希望它是那么简单。但是……通天塔,哟。
  • 但是:postgres 全文搜索是否让我可以像搜索文本一样搜索哈希?要在哈希中查找特定属性?
  • 您从文本中计算出tsvector(这可能是您设想的 PostgreSQL 等价的哈希值),然后使用@@ 运算符搜索tsquery。但是,如果您需要基于文本的语法分析进行匹配(即消除不同的left),则无法通过 PostgreSQl 全文搜索来完成。 PostgreSQL 全文搜索的一个很酷的地方(或者更好的是,其中一个很酷的地方)是它可以使用 GIN 索引非常快。

标签: ruby-on-rails postgresql nlp


【解决方案1】:

一个简单的解决方案是拥有一个包含多个索引的数据库:一个用于基本词,一个用于词性,一个用于您感兴趣的所有其他功能。

当您点击left时,您会发现它是“离开”的一种形式,以及“过去时”中的“动词”。现在你去你的索引,并获得“离开”、“动词”和“过去时”的所有标记位置。您取所有索引位置的交集,剩下的是您所追求的表单的标记位置。

如果您想节省空间,请查看Managing Gigabytes,这是一本关于该主题的优秀书籍。我过去曾用它来完全索引包含数百万个单词的文本语料库(这在 20 年前是相当多的......)

【讨论】:

  • 有趣。谢谢你。当您说“管理多个索引”时,它本质上是文本和单词特征之间的连接表吗?
  • 据我了解,Postgresql 中的外键是一个索引和一个整数。因此,除非我有误解,否则这是我在帖子中引用的 TextWord 表,对吗?有什么区别吗?
  • 可能。我没有使用 Postgres,而是编写了自己的索引文件(按照 MG 书)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
  • 1970-01-01
  • 2021-12-15
相关资源
最近更新 更多