我对 mongodb 比较陌生,到目前为止,我还没有解决我之前用 SQL 后端解决的问题的方法。
问题本身很简单:我在数据库中保存了大量任意长度的有序单词序列,例如:
Sequence #0: [ "word1", "word34", "word56", …, "word_66" ]
Sequence #1: [ "word45", "word2", "word334", "word45", …, "word_668" ]
...
在数据库序列中,同一个词可能会出现不止一次。
给定一个像 ["word2", "word334"] 这样的输入单词序列,我想检索所有包含输入单词的数据库序列,它们的顺序与给定的相同。唯一的特殊性是:输入的单词之间最多可以有一个单词。因此,例如,序列 ["a", "a", "b", "c"] 将匹配输入 ["a", "c"],"b" 是“跳过的单词”在这种情况下。假设在执行任何搜索之前,所有序列都已使用任何数据模型写入数据库;只有查询是感兴趣的。
使用 SQL,这个问题很容易通过对规范化表的单个查询来解决。但我想用 mongoDb 解决同样的问题。
首先,我尝试完全复制 mongoDb 中的表,就像我在 SQL 中一样。我想我会在我去的时候用 mongo 查询语言调整查询。这效果不太好,因为我发现无法在同一个 find() 中比较来自同一个集合的两个文档——(这是模拟某种 JOIN 的幼稚尝试)。
接下来,我尝试在“序列”文档中将序列词分组到一个数组中,并确保所有必要的信息都在同一个文档中可用。使用 aggregate() 管道,我尝试查看是否无法“链接”几个 $match 阶段。在 $match 阶段我能做的最好的事情是过滤其中包含所有输入单词的序列(使用 $all),但我不能再进一步了,因为我永远找不到 mongoDb 的方式来表达“比较位置文档数组中的一个单词到同一个文档数组中另一个单词的位置”(显然,您不能将字段放在查询比较运算符的右侧,即使来自同一个文档)。
然后我虽然可以编写一个javascript函数来计算一个文档的解决方案并在$match之后的$where阶段调用它。这种方法也没有成功,因为我找不到将输入序列(数组变量)传递给 $where 子句的方法。我什至尝试根据输入手动组合查询字符串,以便它只包含解析的常量以在之后运行它,但无济于事(显然,$where 不喜欢将局部变量作为参数传递,并且不像数组常量)。我尝试将功能上传到服务器,以防万一,但我也没有运气,限制似乎或多或少相同。
在这一点上,我能看到的唯一可行的方法是将所有序列单词放在一个大字符串中,并使用 $regex 运算符来执行匹配。这会有点难看,因为可能存在“跳过的单词”,并且因为正则表达式而非常慢,而且因为在这种情况下永远无法使用索引。我没有尝试成熟的 mapReduce 管道,但乍一看它似乎只是对 aggregate() 的扩展,因此可能同样不适合解决这个问题。
我已经浏览了几次文档,并没有发现任何其他可以帮助我的“特殊功能”或概念。有 MongoDB 建模知识的人可以推动我采用一些有效的方法吗?什么可能是一个对 mongoDb 友好的数据模型?我不是在寻找与这个特定问题相关的设计大纲那样多的代码。谢谢。