直接在 MongoDB 中维护索引,避免 Rails 应用程序覆盖它们

Maintain indexes directly in MongoDB and avoid the Rails app overwriting them

我们有两个 Rails 5 个应用共享一个集群 MongoDB,托管在 mlab.com

我们通过模型定义我们的 fields/indexes。这些应用程序彼此不了解 fields/indexes,并且需要保持这种状态:

# app 1
class Order
  include Mongoid::Document
  field :order_number,            type: String
  belongs_to :status,             inverse_of: :orders
  index({ order_number: 1 },      { background: true })
  index({ status_id: 1 },         { background: true })
end

# app 2
class Order
  include Mongoid::Document
  field :order_number,            type: String
  field :internal_comment,        type: String
  index({ order_number: 1 },      { background: true })
  index({ internal_comment: 1 },  { background: true })
end

只有一个应用程序,我们将简单地维护索引:

bundle exec rake db:mongoid:remove_indexes
bundle exec rake db:mongoid:create_indexes

但这会使每个应用取消彼此的索引。

是否可以直接在MongoDB中create/remove建立索引,避免Rails应用覆盖它?


为了更好地了解情况,请考虑以下一系列事件。

首先,app 1 插入新订单:

# app 1
Order.collection.insert_many(
  [
    {_id:             BSON::ObjectId('5b04208483c336a17ada564c'),
      order_number:   "1",
      status_id:      BSON::ObjectId('59db682c17be4a0005eb246a')
    },
    ...
  ]
)

这里我们遇到了 internal_comment 的索引问题,因为索引没有在两个应用程序中注册。

接下来,应用程序 2 查询具有 internal_comment 的订单。如果索引不能正常工作,速度会很慢:

# app 2
Order.collection.find(
  {
    internal_comment: { "$ne": nil }
  }
).to_a

最后,应用 2 更新其中一个订单(由应用 1 插入)。我不确定这会如何影响 status_idinternal_comment 字段的索引。

# app 2 updates the order:
Order.collection.update_one(
  {
    _id:              BSON::ObjectId('5b04208483c336a17ada564c'),
    internal_comment: "foo"
  }
)

首先,不要运行remove_indexes。在我使用 mongodb 和 mongoid.

的 9 年里,我没有做过一次

您写入模型的索引仅用于 create_index rake 任务,没有其他地方(我能想到),我自己的工作流程是通过 [=17= 创建一个新索引] 控制台,通常是在将其添加到模型中以供将来参考之前找出最佳索引变体(毕竟组件的顺序之类的东西很重要)。阅读 mongodb docs about createIndex