Golang中MongoDB的Schema验证实现与技巧

Golang中MongoDB的Schema验证实现与技巧 大家好,

我为MongoDB编写了以下模式验证器,以下是针对名为“posts”的集合的插入查询。基本思路是创建一个博客,包含标题、作者、标签和评论,其中评论是嵌套文档。 我能够成功运行验证器,但无法运行插入查询。模式验证失败了。

db.users.find()
{ _id: ObjectId("647b983d65af5108a7f21679"),
  name: 'shubhra garg',
  age: 34,
  email_id: 'shubhra.garg09@gmail.com' }
{ _id: ObjectId("647b983d65af5108a7f2167a"),
  name: 'ankit garg',
  age: 29,
  email_id: 'gargankit2201@gmail.com' }
{ _id: ObjectId("647b9b0865af5108a7f2167d"),
  name: 'anita agrawal',
  age: 44,
  email_id: 'anita49@gmail.com' }
{ _id: ObjectId("647b9b0865af5108a7f2167e"),
  name: 'sp agrawal',
  age: 64,
  email_id: 'spqagrawal@gmail.com' }
db.createCollection('posts',
                          {validator: {
                              $jsonSchema:{
                                bsonType:'object',
                                required:['title','text','author','comments'],
                                properties:{
                                    title:{
                                        bsonType:'string',
                                        description:"Title is a required field"
                                    },
                                    text:{
                                        bsonType:'string',
                                        description:"Text field is required"
                                    },
                                    author:{
                                        bsonType:'objectId',
                                        description:"Author is required field"
                                    },
                                    comments:{
                                        bsonType:'array',
                                        description:"must be an array of list and is required field",
                                        items:{
                                            bsonType:'objectId',
                                            required:['text','creator'],
                                            properties:{
                                                text:{
                                                    bsonType:'string',
                                                    description:"text is a required field"
                                                },
                                                creator:{
                                                    bsonType:'objectId',
                                                    description:"Creator field is required"
                                                }
                                                
                                            }
                                        }
                                    }
                                }
                            }
                          }
                        }
                    )

分享两个MongoDB的插入查询:

db.posts.insertOne({title: "My first post",text:"Happy me!", author:ObjectId("647b983d65af5108a7f21679"), tags:["new","generation","happy"], comments:[{text:"Good to see you happy", creator:ObjectId("647b983d65af5108a7f2167a")}]})
db.posts.insertOne({title: "My first post",text:"Happy me!", author:ObjectId("647b983d65af5108a7f21679"),comments:[{text:"Good to see you happy", creator:ObjectId("647b9b0865af5108a7f2167d")}]})

更多关于Golang中MongoDB的Schema验证实现与技巧的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

@christophberger 你能帮忙解决这个问题吗?我卡住了。

更多关于Golang中MongoDB的Schema验证实现与技巧的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


@Metalymph 你能帮忙看看这个模式验证的程序吗?

@shubhragrag 抱歉,我不得不拒绝。我对MongoDB的了解仅限于其名称以及它是一个面向文档的数据库这一事实。

第一个查询包含一个 tags 字段,我在 $jsonSchema 中没有看到这个字段,但乍看之下第二个查询似乎没问题。

失败的架构验证是否发出了任何有用的错误信息?

在MongoDB的JSON Schema验证中,你的模式存在几个关键问题。主要问题在于comments字段的验证规则定义不正确。

以下是修正后的模式验证器:

db.createCollection('posts', {
    validator: {
        $jsonSchema: {
            bsonType: 'object',
            required: ['title', 'text', 'author', 'comments'],
            properties: {
                title: {
                    bsonType: 'string',
                    description: "Title is a required field"
                },
                text: {
                    bsonType: 'string',
                    description: "Text field is required"
                },
                author: {
                    bsonType: 'objectId',
                    description: "Author is required field"
                },
                tags: {
                    bsonType: 'array',
                    description: "Optional array of tags",
                    items: {
                        bsonType: 'string'
                    }
                },
                comments: {
                    bsonType: 'array',
                    description: "must be an array of comment objects",
                    items: {
                        bsonType: 'object',
                        required: ['text', 'creator'],
                        properties: {
                            text: {
                                bsonType: 'string',
                                description: "text is a required field"
                            },
                            creator: {
                                bsonType: 'objectId',
                                description: "Creator field is required"
                            }
                        }
                    }
                }
            }
        }
    }
})

主要修正点:

  1. comments.items.bsonType应该是'object'而不是'objectId',因为每个评论是一个包含textcreator的对象
  2. 添加了tags字段的定义(虽然它不是必需的,但明确声明有助于文档结构清晰)

在Go中实现MongoDB插入时,可以使用以下代码示例:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Post struct {
    ID       primitive.ObjectID   `bson:"_id,omitempty"`
    Title    string               `bson:"title"`
    Text     string               `bson:"text"`
    Author   primitive.ObjectID   `bson:"author"`
    Tags     []string             `bson:"tags,omitempty"`
    Comments []Comment            `bson:"comments"`
}

type Comment struct {
    Text    string               `bson:"text"`
    Creator primitive.ObjectID   `bson:"creator"`
}

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect(ctx)

    collection := client.Database("test").Collection("posts")

    // 创建验证器
    validator := bson.M{
        "$jsonSchema": bson.M{
            "bsonType": "object",
            "required": []string{"title", "text", "author", "comments"},
            "properties": bson.M{
                "title": bson.M{
                    "bsonType":    "string",
                    "description": "Title is a required field",
                },
                "text": bson.M{
                    "bsonType":    "string",
                    "description": "Text field is required",
                },
                "author": bson.M{
                    "bsonType":    "objectId",
                    "description": "Author is required field",
                },
                "tags": bson.M{
                    "bsonType":    "array",
                    "description": "Optional array of tags",
                    "items": bson.M{
                        "bsonType": "string",
                    },
                },
                "comments": bson.M{
                    "bsonType":    "array",
                    "description": "must be an array of comment objects",
                    "items": bson.M{
                        "bsonType": "object",
                        "required": []string{"text", "creator"},
                        "properties": bson.M{
                            "text": bson.M{
                                "bsonType":    "string",
                                "description": "text is a required field",
                            },
                            "creator": bson.M{
                                "bsonType":    "objectId",
                                "description": "Creator field is required",
                            },
                        },
                    },
                },
            },
        },
    }

    // 创建集合时应用验证器
    opts := options.CreateCollection().SetValidator(validator)
    err = client.Database("test").CreateCollection(ctx, "posts", opts)
    if err != nil {
        // 如果集合已存在,可以忽略这个错误
        fmt.Printf("Collection creation error (may already exist): %v\n", err)
    }

    // 插入示例数据
    authorID, _ := primitive.ObjectIDFromHex("647b983d65af5108a7f21679")
    creatorID, _ := primitive.ObjectIDFromHex("647b983d65af5108a7f2167a")

    post := Post{
        Title:  "My first post",
        Text:   "Happy me!",
        Author: authorID,
        Tags:   []string{"new", "generation", "happy"},
        Comments: []Comment{
            {
                Text:    "Good to see you happy",
                Creator: creatorID,
            },
        },
    }

    result, err := collection.InsertOne(ctx, post)
    if err != nil {
        log.Fatalf("Insert failed: %v", err)
    }

    fmt.Printf("Inserted post with ID: %v\n", result.InsertedID)
}

这个Go代码示例展示了:

  1. 使用Go结构体定义数据模型
  2. 使用bson.M构建JSON Schema验证器
  3. 在创建集合时应用验证规则
  4. 正确插入符合验证规则的文档

验证失败通常是因为模式定义与插入数据不匹配。确保comments数组中的每个元素都是包含text(字符串)和creator(ObjectId)的对象,而不是直接使用ObjectId。

回到顶部