使用Golang实现MongoDB Shell功能
使用Golang实现MongoDB Shell功能 我的数据在MongoDB中以树形结构模型存储。以下是我的数据结构:

以下是我用于创建集合的Mongo Shell脚本:
db.users.insert({_id:"DHBK",username:"DHBK",password:"123456",lastname:"DHBK",user_email:"dhbk@edu.com.vn",user_tel:"0907111001",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:null,com_id:"DHBK",com_department:"DHBK",user_code:"DHBK_0001",user_type:"ADMIN_COM"});
db.users.insert({_id:"KHOA_DIEN",username:"KHOA_DIEN",password:"123456",lastname:"KHOA_DIEN",user_email:"KHOA_DIEN@edu.com.vn",user_tel:"0907111002",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"DHBK",com_id:"DHBK",com_department:"KHOA_DIEN",user_code:"DHBK_0002",user_type:"USER_COM"});
db.users.insert({_id:"KHOA_XD",username:"KHOA_XD",password:"123456",lastname:"KHOA_XD",user_email:"KHOA_XD@edu.com.vn",user_tel:"0907111003",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"DHBK",com_id:"DHBK",com_department:"KHOA_XD",user_code:"DHBK_0003",user_type:"USER_COM"});
db.users.insert({_id:"KHOA_CNTT",username:"KHOA_CNTT",password:"123456",lastname:"KHOA_CNTT",user_email:"KHOA_CNTT@edu.com.vn",user_tel:"0907111004",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"DHBK",com_id:"DHBK",com_department:"KHOA_CNTT",user_code:"DHBK_0004",user_type:"USER_COM"});
db.users.insert({_id:"BOMON_TUDONG",username:"BOMON_TUDONG",password:"123456",lastname:"BOMON_TUDONG",user_email:"BOMON_TUDONG@edu.com.vn",user_tel:"0907111005",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"KHOA_DIEN",com_id:"DHBK",com_department:"KHOA_DIEN",user_code:"DHBK_0005",user_type:"USER_COM"});
db.users.insert({_id:"BOMON_VIENTHONG",username:"BOMON_VIENTHONG",password:"123456",lastname:"BOMON_VIENTHONG",user_email:"BOMON_VIENTHONG@edu.com.vn",user_tel:"0907111006",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"KHOA_DIEN",com_id:"DHBK",com_department:"KHOA_DIEN",user_code:"DHBK_0006",user_type:"USER_COM"});
db.users.insert({_id:"BOMON_HETHONG",username:"BOMON_HETHONG",password:"123456",lastname:"BOMON_HETHONG",user_email:"BOMON_HETHONG@edu.com.vn",user_tel:"0907111007",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"KHOA_DIEN",com_id:"DHBK",com_department:"KHOA_DIEN",user_code:"DHBK_0007",user_type:"USER_COM"});
db.users.insert({_id:"BOMON1_XD",username:"BOMON1_XD",password:"123456",lastname:"BOMON1_XD",user_email:"BOMON1_XD@edu.com.vn",user_tel:"0907111008",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"KHOA_XD",com_id:"DHBK",com_department:"KHOA_XD",user_code:"DHBK_0008",user_type:"USER_COM"});
db.users.insert({_id:"BOMON2_XD",username:"BOMON2_XD",password:"123456",lastname:"BOMON2_XD",user_email:"BOMON2_XD@edu.com.vn",user_tel:"0907111009",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"KHOA_XD",com_id:"DHBK",com_department:"KHOA_XD",user_code:"DHBK_0009",user_type:"USER_COM"});
db.users.insert({_id:"BOMON3_XD",username:"BOMON3_XD",password:"123456",lastname:"BOMON3_XD",user_email:"BOMON3_XD@edu.com.vn",user_tel:"0907111010",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"KHOA_XD",com_id:"DHBK",com_department:"KHOA_XD",user_code:"DHBK_0010",user_type:"USER_COM"});
db.users.insert({_id:"TRUONGKHOA_BMVT",username:"TRUONGKHOA_BMVT",password:"123456",lastname:"TRUONGKHOA_BMVT",user_email:"TRUONGKHOA_BMVT@edu.com.vn",user_tel:"0907111011",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"BOMON_VIENTHONG",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0011",user_type:"USER_COM"});
db.users.insert({_id:"PHOKHOA_BMVT",username:"PHOKHOA_BMVT",password:"123456",lastname:"PHOKHOA_BMVT",user_email:"PHOKHOA_BMVT@edu.com.vn",user_tel:"0907111012",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"BOMON_VIENTHONG",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0012",user_type:"USER_COM"});
db.users.insert({_id:"THUKY_BMVT",username:"THUKY_BMVT",password:"123456",lastname:"THUKY_BMVT",user_email:"THUKY_BMVT@edu.com.vn",user_tel:"0907111013",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"BOMON_VIENTHONG",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0013",user_type:"USER_COM"});
db.users.insert({_id:"GV_BMVT",username:"GV_BMVT",password:"123456",lastname:"GV_BMVT",user_email:"GV_BMVT@edu.com.vn",user_tel:"0907111014",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"BOMON_VIENTHONG",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0014",user_type:"USER_COM"});
db.users.insert({_id:"SV1_BMVT",username:"SV1_BMVT",password:"123456",lastname:"SV1_BMVT",user_email:"SV1_BMVT@edu.com.vn",user_tel:"0907111015",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"GV_BMVT",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0015",user_type:"USER_COM"});
db.users.insert({_id:"SV2_BMVT",username:"SV2_BMVT",password:"123456",lastname:"SV2_BMVT",user_email:"SV2_BMVT@edu.com.vn",user_tel:"0907111016",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"GV_BMVT",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0016",user_type:"USER_COM"});
db.users.insert({_id:"SV3_BMVT",username:"SV3_BMVT",password:"123456",lastname:"SV3_BMVT",user_email:"SV3_BMVT@edu.com.vn",user_tel:"0907111017",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"GV_BMVT",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0017",user_type:"USER_COM"});
db.users.insert({_id:"SV4_BMVT",username:"SV4_BMVT",password:"123456",lastname:"SV4_BMVT",user_email:"SV4_BMVT@edu.com.vn",user_tel:"0907111018",user_date:"2020-05-05",user_status:"ACTIVE",user_parentid:"GV_BMVT",com_id:"DHBK",com_department:"BOMON_VIENTHONG",user_code:"DHBK_0018",user_type:"USER_COM"});
在我的实践中,我想删除父节点,这意味着要删除所有后代节点。
例如: 当我删除 “BOMON_VIENTHONG” 节点时,必须同时删除 TRUONGKHOA_BMVT、PHOKHOA_BMVT、THUKY_BMVT、GV_BMVT、SV1_BMVT、SV2_BMVT、SV3_BMVT、SV4_BMVT。
我可以使用Mongo Shell来执行这个删除操作。以下是我的Mongo Shell脚本:
TOP_LEVEL_PARENT = "BOMON_VIENTHONG"
db.users.aggregate( [
{
$graphLookup: {
from: "users",
startWith: "$user_parentid",
connectFromField: "user_parentid",
connectToField: "_id",
as: "hierarchy"
}
},
{
$match: {
$or: [
{ "hierarchy._id": TOP_LEVEL_PARENT },
{ _id: TOP_LEVEL_PARENT }
]
}
}
]
).forEach( doc => db.users.deleteOne( { _id: doc._id } ) )
我想在Go语言中实现这个Mongo Shell脚本。我是Go语言的初学者。
请帮助我。
提前感谢。
更多关于使用Golang实现MongoDB Shell功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
我正在使用 mgo。 但这个语法对我来说非常复杂。 请帮我将其转换为 mgo 语法。
TOP_LEVEL_PARENT = "BOMON_VIENTHONG"
db.users.aggregate( [
{
$graphLookup: {
from: "users",
startWith: "$user_parentid",
connectFromField: "user_parentid",
connectToField: "_id",
as: "hierarchy"
}
},
{
$match: {
$or: [
{ "hierarchy._id": TOP_LEVEL_PARENT },
{ _id: TOP_LEVEL_PARENT }
]
}
}
]
).forEach( doc => db.users.deleteOne( { _id: doc._id } ) )
在Go语言中实现MongoDB Shell的树形结构删除功能,可以使用官方的MongoDB Go驱动。以下是完整的示例代码:
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
ID string `bson:"_id"`
Username string `bson:"username"`
Password string `bson:"password"`
Lastname string `bson:"lastname"`
UserEmail string `bson:"user_email"`
UserTel string `bson:"user_tel"`
UserDate string `bson:"user_date"`
UserStatus string `bson:"user_status"`
UserParentID string `bson:"user_parentid"`
ComID string `bson:"com_id"`
ComDepartment string `bson:"com_department"`
UserCode string `bson:"user_code"`
UserType string `bson:"user_type"`
}
func deleteNodeAndDescendants(parentID string) error {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
return fmt.Errorf("连接MongoDB失败: %v", err)
}
defer client.Disconnect(ctx)
collection := client.Database("test").Collection("users")
pipeline := mongo.Pipeline{
bson.D{
{"$graphLookup", bson.D{
{"from", "users"},
{"startWith", "$user_parentid"},
{"connectFromField", "user_parentid"},
{"connectToField", "_id"},
{"as", "hierarchy"},
}},
},
bson.D{
{"$match", bson.D{
{"$or", bson.A{
bson.D{{"hierarchy._id", parentID}},
bson.D{{"_id", parentID}},
}},
}},
},
}
cursor, err := collection.Aggregate(ctx, pipeline)
if err != nil {
return fmt.Errorf("聚合查询失败: %v", err)
}
defer cursor.Close(ctx)
var usersToDelete []User
if err = cursor.All(ctx, &usersToDelete); err != nil {
return fmt.Errorf("读取结果失败: %v", err)
}
for _, user := range usersToDelete {
_, err := collection.DeleteOne(ctx, bson.D{{"_id", user.ID}})
if err != nil {
return fmt.Errorf("删除用户 %s 失败: %v", user.ID, err)
}
fmt.Printf("已删除: %s\n", user.ID)
}
fmt.Printf("成功删除 %d 个节点\n", len(usersToDelete))
return nil
}
func main() {
parentID := "BOMON_VIENTHONG"
if err := deleteNodeAndDescendants(parentID); err != nil {
log.Fatal(err)
}
}
如果需要更高效的递归删除实现,可以使用以下方法:
func deleteNodeAndDescendantsRecursive(parentID string) error {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
return fmt.Errorf("连接MongoDB失败: %v", err)
}
defer client.Disconnect(ctx)
collection := client.Database("test").Collection("users")
var deleteIDs []string
deleteIDs = append(deleteIDs, parentID)
for i := 0; i < len(deleteIDs); i++ {
currentID := deleteIDs[i]
cursor, err := collection.Find(ctx, bson.D{{"user_parentid", currentID}})
if err != nil {
return fmt.Errorf("查找子节点失败: %v", err)
}
var children []User
if err = cursor.All(ctx, &children); err != nil {
cursor.Close(ctx)
return fmt.Errorf("读取子节点失败: %v", err)
}
cursor.Close(ctx)
for _, child := range children {
deleteIDs = append(deleteIDs, child.ID)
}
}
for _, id := range deleteIDs {
_, err := collection.DeleteOne(ctx, bson.D{{"_id", id}})
if err != nil {
return fmt.Errorf("删除节点 %s 失败: %v", id, err)
}
fmt.Printf("已删除: %s\n", id)
}
fmt.Printf("成功删除 %d 个节点\n", len(deleteIDs))
return nil
}
使用BulkWrite进行批量删除的优化版本:
func deleteNodeAndDescendantsBulk(parentID string) error {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
return fmt.Errorf("连接MongoDB失败: %v", err)
}
defer client.Disconnect(ctx)
collection := client.Database("test").Collection("users")
pipeline := mongo.Pipeline{
bson.D{
{"$graphLookup", bson.D{
{"from", "users"},
{"startWith", "$user_parentid"},
{"connectFromField", "user_parentid"},
{"connectToField", "_id"},
{"as", "hierarchy"},
{"maxDepth", 10},
{"depthField", "depth"},
}},
},
bson.D{
{"$match", bson.D{
{"$or", bson.A{
bson.D{{"hierarchy._id", parentID}},
bson.D{{"_id", parentID}},
}},
}},
},
bson.D{
{"$project", bson.D{
{"_id", 1},
}},
},
}
cursor, err := collection.Aggregate(ctx, pipeline)
if err != nil {
return fmt.Errorf("聚合查询失败: %v", err)
}
defer cursor.Close(ctx)
var results []bson.M
if err = cursor.All(ctx, &results); err != nil {
return fmt.Errorf("读取结果失败: %v", err)
}
var models []mongo.WriteModel
for _, result := range results {
id := result["_id"].(string)
model := mongo.NewDeleteOneModel().SetFilter(bson.D{{"_id", id}})
models = append(models, model)
}
if len(models) > 0 {
opts := options.BulkWrite().SetOrdered(false)
result, err := collection.BulkWrite(ctx, models, opts)
if err != nil {
return fmt.Errorf("批量删除失败: %v", err)
}
fmt.Printf("成功删除 %d 个文档\n", result.DeletedCount)
}
return nil
}
安装MongoDB Go驱动:
go get go.mongodb.org/mongo-driver/mongo
这些代码实现了与Mongo Shell脚本相同的功能,可以删除指定节点及其所有后代节点。


