9

I have a collection that looks like this:

{
  "_id": "5c90e8736441c96cc8e5c703",
  "meta": {
    "schemaVersion": 1,
    "locHint": {
      "region": "150",
      "country": "GBR"
    }
  },
  "name": "My test study"
}

And the following validator:

{
  "$jsonSchema": {
    "bsonType": "object",
    "required": [
      "meta.schemaVersion"
      "meta.locHint.region",
      "meta.locHint.country",
      "name"
    ],
    "properties": {
      "meta.schemaVersion": {
        "bsonType": "int",
        "description": "Version counter used schema changes"
      },
      "meta.locHint.region": {
        "bsonType": "string",
        "pattern": "^[0-9]{3}$",
        "description": "meta.locHint.region is required to be a valid iso3166 region  (3 digits)"
      },
      "meta.locHint.country": {
        "bsonType": "string",
        "pattern": "^[A-Z]{3}$",
        "description": "meta.locHint.country is required to be a valid iso3166 alpha-3  (3 upper case letters)"
      },
      "name": {
        "bsonType": "string",
        "description": "name is required and must be a string"
      }
    }
  }
}

What do I want to achieve is: rename (update) region to m46Region, country to iso3166Country and change the pattern for meta.locHint.country using a MongoBee migration script.

When I try to do that, mongo says that my document is not valid and it's not allowing me to rename the fields.

How do I update the validators as well? or remove and recreate them?

4

1 回答 1

1

我设法做到了,不确定这是否是正确的方法,但它完成了工作。

首先你必须关闭validationLevel并抑制validationAction中的错误

private def disableValidators(db: DB, collectionName: String): Unit = {
  val command = new BasicDBObject("collMod", collectionName)
    .append("validationLevel", "off")
    .append("validationAction", "warn")

  db.command(command)
}

添加新字段并重命名其他字段。

private def addRenameLocationHintFields(collection: DBCollection): Unit = {
  val findQuery = new BasicDBObject()
  val addFieldIso3166Subdivision = new BasicDBObject("$set", new BasicDBObject("meta.locHint.iso3166Subdivision", null))
  collection.updateMulti(findQuery, addFieldIso3166Subdivision)

  val renameRegion = new BasicDBObject("$rename", new BasicDBObject("meta.locHint.region", "meta.locHint.m49Region"))
  collection.updateMulti(findQuery, renameRegion)

  val renameCountry = new BasicDBObject("$rename", new BasicDBObject("meta.locHint.country", "meta.locHint.iso3166CountryA2"))
  collection.updateMulti(findQuery, renameCountry)
}

如果您已为字段编制索引,则需要删除并重新创建它们。

collection.dropIndex("locHint")
  collection.createIndex(
    BasicDBObjectBuilder
      .start()
      .add("meta.locHint.m49Region", 1)
      .add("meta.locHint.iso3166CountryA2", 1)
      .add("meta.locHint.iso3166Subdivision", 1)
      .add("_id", 1)
      .get()
  )

更新验证器,旧的集合验证器将被新的验证器替换。

private def updateValidators(db: DB, collectionName: String): Unit = {
  val command = BasicDBObjectBuilder
    .start()
    .add("collMod", collectionName)
    .add(
      "validator",
      BasicDBObjectBuilder
      .start()
      .add(
        "$jsonSchema",
        BasicDBObjectBuilder
          .start()
          .add("bsonType", "object")
          .add(
            "required",
            Array(
              "meta.schemaVersion",
              "meta.locHint.m49Region",
              "meta.locHint.iso3166CountryA2",
              "name"
            )
          )
          .add(
            "properties",
            BasicDBObjectBuilder
              .start()
              .add(
                "meta.schemaVersion",
                BasicDBObjectBuilder
                  .start()
                  .add("bsonType", "int")
                  .add("description", "Version counter used schema changes")
                  .get()
              )
              .add(
                "meta.locHint.m49Region",
                BasicDBObjectBuilder
                  .start()
                  .add("bsonType", "string")
                  .add("pattern", "^[0-9]{3}$")
                  .add("description", "meta.locHint.m49Region is required to be a valid iso3166 region  (3 digits)")
                  .get()
              )
              .add(
                "meta.locHint.iso3166CountryA2",
                BasicDBObjectBuilder
                  .start()
                  .add("bsonType", "string")
                  .add("pattern", "^[A-Z]{2}$")
                  .add("description", "meta.locHint.iso3166CountryA2 is required to be a valid iso3166 alpha-2  (2 upper case letters)")
                  .get()
             )
              .add(
                "name",
                BasicDBObjectBuilder
                  .start()
                  .add("bsonType", "int")
                  .add("description", "Version of the terms of service that the user has accepted")
                  .get()
              )
              .get()
          )
        .get()
      )
      .get()
  )

  db.command(command.get())
}

启用验证器。

private def enableValidators(db: DB, collectionName: String): Unit = {
  val command = new BasicDBObject("collMod", collectionName)
    .append("validationLevel", "strict")
    .append("validationAction", "error")

  db.command(command)
}

那应该做的工作。

于 2019-03-21T13:41:37.837 回答