带有 MongoDB 的 Grails - 如何定义嵌套和可重用的字段

Grails with MongoDB - how to define nested and reusable fields

我正在尝试用 grails 重写我的 node.js + express 后端。我正在使用 MongoDB 数据库,其中嵌套字段很常见。在我当前的后端中,我定义了一个模式(使用猫鼬),其中包含一个字段,例如:

normalized: {
    full_name: {type: String, trim: true, index: true}
},

我还定义了一个名为“locationSchema”的独立、可重复使用的架构,我可以将其用于我的许多领域,如下所示:

// Definition of reusable "sub-schema"
const locationSchema = new mongoose.Schema({
    country: {type: String, trim: true},
    region: {type: String, trim: true},
    city: {type: String, trim: true},
    notes: String,
    latitude: {type: Number},
    longitude: {type: Number}
}, {_id: false});

然后使用它,例如,定义 birth 字段:

birth: {
    date: {type: dateSchema, validate: dateValidator},
    location: locationSchema,
    notes: String
},

除了可以将嵌套字段定义为 Map 之外,我没有找到太多关于此的信息,但我如何将约束应用于子字段?我将如何在 Grails 中使用“子模式”?


更新解决方案

我误解了 embedded 的用法。如果您(像我一样)不想为嵌入式类型创建 tables/collections,只需将嵌入式 class(如我的 Location)放在 src/main/... 下或将其定义在与域 class 相同的文件。这在文档中有说明:http://docs.grails.org/3.1.1/ref/Domain%20Classes/embedded.html

我最终的简化解决方案是:

grails-app/.../Person.groovy

class Person implements MongoEntity<Testy> {

    ObjectId id
    String s
    Location location

    static mapping = {
        collection "person"

    }

    static embedded = ['location']  // key part that was missing
}

src/main/.../Location.groovy

package hegardt.backend.grails.model.person

import grails.validation.Validateable


class Location implements Validateable {

    String country
    String region
    String city
    String notes
    Double latitude
    Double longitude

    static constraints = {
        country nullable: true
        region nullable: true
        city nullable: true
        notes nullable: true
        latitude nullable: true
        longitude nullable: true
    }
}

现在我可以发送带有 JSON 数据的请求,并且映射和保存工作正常,并且对我的嵌入式类型进行验证!

您应该为您的案例使用 embedded 对象。

class User {

  Birth birth

  static embedded = [ 'birth' ]

}

class Birth {
  Date date
  Location location
  String notes

  static constraints = {
    date validator:dateValidator
  }
}

那么如果你这样做:

User u = new User()
u.birth = new Birth(...)
u.save()

birth 将保存为 User 中的子文档。

如果你说:

new Birth(...).save()

然后 GORM 创建一个新的集合并照常填写记录。