让我们说我有一本这样的书:
{ title: "Tis no book"
chapter: 1,
text: "Hello world this is a book chapter",
subchapters: [
{
chapter: 1.1
text: "Nested sub chapter"
subchapters: [
chapter: 1.1.1
text: "Nested nested..."
subchapters: [ ...etc...]
},
{
chapter: 1.2
text: "Nested sub chapter 2"
subchapters: [ ...etc...]
}
]
}
我可以使用postgres' 9.4新的jsonb / gin(或其他任何东西)在这个递归嵌套数据结构的"text"
字段上设置全文索引,以便可以通过文本搜索存储到数据库的书库(使用索引) )?
答案 0 :(得分:4)
我刚开始研究全文搜索和jsonb类型。一旦了解索引如何在JSONB类型上工作,看起来这是可能的。我发现这个博客系列非常有用。
https://bibhas.in/blog/postgresql-swag-part-2-indexing-json-data-type-and-full-text-search/
此外,Postgres的JSON类型文档包含一些很好的见解。 http://www.postgresql.org/docs/9.4/static/datatype-json.html
答案 1 :(得分:2)
一个选项 - 可能是最好的 - 是创建一个递归函数(official documentation on functions),它将整个JSONB结构的text
值组合成一个字符串(它返回)。您可以对该函数的输出进行全文索引(请参阅@ thomas-wayne-shelton的答案),就像它只是一个字符串一样。只要在WHERE
条件中使用相同的函数,pgSQL就应该识别索引。
我刚刚建立/测试了类似的"展平"功能,所以我相信它可以做到。不幸的是,我的情况非常不同所以我怀疑代码会混淆而不是启发。我可以说必须将函数标记为IMMUTABLE以支持索引。
===
看起来很有希望的另一条道路(但我认为是一个死胡同)是一个递归的CTE。
使用递归CTE打包递归数据当然是可能的。这里是official documentation,SO answer和blog example - 特别是递归嵌套JSONB的最后两个。
但是,我不相信你可以索引这个输出。我(暂时)理解使用递归CTE的查询很像视图。它是运行时优化。我现在不再参考了,但回想起最近(截至2018年4月)的讨论,索引视图还有很长的路要走(我甚至不确定视图上的索引是否真的适用于CTE )。
答案 2 :(得分:-1)
我不会回答这个问题;相反,我将建议一种完全不同的方法。
你看过Lucene https://lucene.apache.org/core/了吗?在数据库中实现全文搜索是糟糕的设计。您应该使用单独的全文索引器,例如Lucene。 Lucene文档应该引用可用于在数据库中查找真实记录的数据库密钥。
通过使用Lucene,您最有可能获得比使用数据库的全文搜索功能更好的性能。此外,Lucene比数据库更容易扩展。