MongoDB normalized/indexed 模型上的 Atlas 搜索索引

MongoDB Atlas Search index on normalized/indexed model

我想使用新的 Atlas 搜索索引功能来搜索我的模型。

在我看来,我使用的数据模型无法与此 mongo 功能相结合。 它似乎在嵌入式模型上工作得很好,但出于一致性原因我不能嵌套 objects,它们由它们的 id 引用。

例子

Collection 产品

{
  name: "Foo product"
  quantity: 3
  tags: [
    "id_123"
  ]
}

Collection 供应商

{
  name: "Bar vendor"
  address: ...
  tags: [
    "id_123"
  ]
}

Collection 标签

{
  id: "id_123"
  name: "food"
}

我想要的

I want to type food in my search bar, and find the products associated to the tag food.

详细问题

我有多个商家 object,它们都标有相同的标签。我想建立一个搜索索引来搜索我的产品,但我想 $lookup 之前对我的 ID 进行非规范化并能够找到所有带有标签“食物”的产品。

根据文档,$search operator 必须是聚合管道的第一个运算符,这使我无法在搜索之前进行查找。我有想法首先构建一个视图,用正确的标签解压 id 以准备字段。但是不可能在视图上建立搜索索引。

完全不可能完成这项工作吗?我是否需要通过扁平化和将每个标签直接嵌入每个模型来放弃标签的一致性?我需要它们才能使用此功能吗?这意味着如果我想更新标签,我需要找到每个带有标签的企业 object,然后执行更新 ?

我联系了 MongoDB 支持,Atlas Search 提出了三种方法来解决这个问题。如果有人遇到与我由于此模型设计而不得不经历的相同问题,我想与您分享解决方案。

推荐:以Embedded方式改造模型

理想的 MongoDB 方法是对模型进行非规范化,而不是使用对各种模型的引用。它有一些缺点,比如痛苦的更新:每个标签都将直接添加到 Product 和 Vendor 模型中,因此不再需要 $lookup 操作。对我来说,它是一个no-go,标签计划是可更新的,并且将在几乎每个业务中共享objects我打算制作一个模型。

Collection 产品

{
  name: "Foo product"
  quantity: 3
  tags: [
    "food"
  ]
}

Collection 供应商

{
  name: "Bar vendor"
  address: ...
  tags: [
    "food"
  ]
}

不推荐但可行:将请求分成多个部分

这意味着要保留现有模型,并在应用程序端单独请求 collection 并解决顺序请求。

我们可以在标签 collection 上放置一个 Atlas 搜索索引,然后使用研究功能找出我们想要的标签的 id。那么我们就可以使用这个id直接在Product/Vendorcollection中fetch,找到“food”标签对应的商品。通过修补搜索应用端,我们可以获得令人满意的结果。

这不是推荐的做法。

理论上我的首选方式:使用物化视图功能

这是一个中间解决方案,这将是我要尝试的解决方案。它并不完美,但就我所见,它试图调和参考模型和嵌入式模型的功能。

Atlas Search 索引不可用于常规视图。可以使这成为可能的解决方法是实体化视图(比确定的视图更多collection)。这是通过使用 $merge 运算符实现的,该运算符可以将聚合管道的结果保存在 collection 中。通过re-running管道,我们可以更新物化视图。诀窍是使所有必需的 $lookup 操作对引用模型进行非规范化。然后使用 $merge 运算符作为最后一步,从头开始创建支持 Atlas 搜索索引的 collection,就像任何 collection.

唯一需要注意的是为更新实体化视图选择的更新间隔,这可能是性能贪婪的。但从表面上看,对于像我这样不能(不会?)为嵌入式模型的痛苦更新策略付出代价的人来说,这是一个非常好的解决方案。