Средство проверки обновлений MongoDB

#mongodb #mongobee

#mongodb #mongobee

Вопрос:

У меня есть коллекция, которая выглядит следующим образом:

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

И следующий средство проверки:

 {
  "$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"
      }
    }
  }
}
  

Чего я хочу добиться, так это переименовать (обновить) регион на m46Region, страну на iso3166Country и изменить шаблон для meta.locHint.country с помощью скрипта миграции MongoBee.

Когда я пытаюсь это сделать, mongo сообщает, что мой документ недействителен, и это не позволяет мне переименовывать поля.

Как мне также обновить средства проверки? или удалить и создать их заново?

Ответ №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)
}
  

Это должно выполнить свою работу.