Golang中MongoDB的插入操作如何实现?

Golang中MongoDB的插入操作如何实现? 大家好,

我有一个存储大量数据的数组,需要将这些数据插入到MongoDB中。

我能够使用以下代码实现这一目标,但耗时较长。是否有其他方法可以将大型数组数据推送到MongoDB中?

session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)

c := session.DB("Test").C("Indicators")

for i := 0; i < len(HeadDet); i++ {
    err = c.Insert(HeadDet[i])
}
if err != nil {
    log.Fatal(err)
}

我已参考以下链接: https://labix.org/mgo

谢谢。


更多关于Golang中MongoDB的插入操作如何实现?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

14 回复

谢谢。有这方面的示例吗?

更多关于Golang中MongoDB的插入操作如何实现?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你同时运行多少个 goroutine?每个 goroutine 是否有自己的会话副本?你会关闭会话吗?

你收到什么错误信息了?有更多详细信息吗?"它不工作"这样的描述无法帮助我们帮助你。具体是什么不工作?它是怎么不工作的?

我尝试按照建议使用 goroutine 将数据插入到 MongoDB 中。但是对于 50 到 100 条记录它可以正常工作,而对于大量记录却无法工作。有人能帮忙解决这个问题吗?

感谢。我已经处理了错误。但它没有插入到数据库中。也没有抛出任何错误。我用一些会生成50到100条记录的测试数据检查了相同的代码,这些记录都成功插入到数据库中没有问题。只有大数据量(300万条记录)才会出现这个问题。

Alex_Roz:

col.Insert(doc…)

文档显示 col.Insert() 会返回一个错误,而你忽略了它。可以这样做来了解问题所在:

err := col.Insert(doc...)
if err != nil {
   fmt.Errorf("insert error: %s\n", err) //
}

关键在于:永远不要忽略错误,务必处理它们。

感谢您的建议。我能够在3分钟内存储约30万条记录。

使用以下代码:

//HeadDet 包含30万条记录
docs := make([]interface{}, len(HeadDet))
for i := range HeadDet{
docs[i] = HeadDet[i]
}
//将文档插入数据库
collection.Insert(docs...)

但我希望能在几秒钟内插入数组数据,而不是3分钟。迭代数组数据很耗时。有没有其他方法可以将时间减少到几秒钟?

谢谢。

使用工作线程(goroutine)并在每个线程中创建独立的mgo会话(多连接)。请参考mgo会话的Copy()方法。具体执行速度取决于您的Mongo服务器性能。

// 示例代码展示如何在工作线程中使用独立的mgo会话
func worker(session *mgo.Session, jobs <-chan Job) {
    // 为每个工作线程创建会话副本
    localSession := session.Copy()
    defer localSession.Close()
    
    for job := range jobs {
        // 处理任务...
    }
}

mgo 的文档说明可以使用 insert 方法插入一个或多个文档。链接

可能会出现一个问题,即插入的数组最终可能只有一个单一 ID(如此处所述)。

MongoDB 本身有一个 db.collection.insertmany() 方法。但不确定 mgo 是否实现了它。

抱歉没能提供太多帮助。

那么如何判断它没有正常工作呢?你怎么知道出现了错误?是你的程序确实结束了,然后你检查数据库发现没有插入数据吗?日志是否显示有任何尝试插入数据的记录?等等。

你提供的示例代码并不完整,而且你提供的信息量太少,我们难以提供帮助。请提供更多细节,并开始进行调试工作,可以在代码中适当位置添加一些打印语句,甚至可以使用调试器(例如 https://github.com/derekparker/delve)。

另外需要说明的是,尽管那个特定的调用可能没有抛出错误,但我还是要强调你应该始终检查并处理错误。

我不确定 mgo 是否使用与我了解的其他语言数据库驱动类似的术语,但我会查看 Bulk 方法。

此外,似乎你应该寻找另一个驱动,因为 mgo 看起来已不再维护:

mgo package - gopkg.in/mgo.v2 - Go Packages

#########################################################

此驱动已不再维护!详情请见:

mgo/README.md at v2-unstable · go-mgo/mgo · GitHub

#########################################################

我没有收到任何错误信息。程序能够成功向MongoDB插入50到100条记录。但当我尝试插入大量记录时,数据无法插入数据库。我使用的是以下代码:

package test

    import (
     "os"

    "gopkg.in/mgo.v2"
      )

   var Db *mgo.Session

  type DbLink struct {
  DbName string
 }

func NewDbSession(url string) {
var e error   

Db, e = mgo.Dial(url)

if e != nil {
	panic(e)
	os.Exit(-1)
}
}

func PerformInsertOperation() {

NewDbSession("localhost")
session := Db.Copy()
//defer session.Close()

col := session.DB("TEST").C("HeadDet")
ch := make(chan bool)

go func(doc []interface{}) {

	col.Insert(doc...)

	ch <- true

}(HeadDet)

 }

谢谢。

我在一个项目中切换到了这个分支

GitHub

globalsign/mgo

Go语言的MongoDB驱动。通过在GitHub上创建账户来为globalsign/mgo开发做贡献。

因为官方驱动仍处于alpha阶段。

globalsign/mgo/blob/1ca0a4f7cbcbe61c005d1bd43fdd8bb8b71df6bc/bulk.go#L171

		action = &b.actions[len(b.actions)-1]
	}
	for i := 0; i < opcount; i++ {
		action.idxs = append(action.idxs, b.opcount)
		b.opcount++
	}
	return action
}

// Insert queues up the provided documents for insertion.
func (b *Bulk) Insert(docs ...interface{}) {
	action := b.action(bulkInsert, len(docs))
	action.docs = append(action.docs, docs...)
}

// Remove queues up the provided selectors for removing matching documents.
// Each selector will remove only a single matching document.
func (b *Bulk) Remove(selectors ...interface{}) {
	action := b.action(bulkRemove, len(selectors))
	for _, selector := range selectors {
		if selector == nil {

遗憾的是,这个驱动不支持用于取消操作的上下文方法,而官方驱动支持。

在Golang中使用mgo库插入大量数据时,使用Insert方法进行单条插入确实会导致性能问题。对于批量插入,可以使用Insert方法的变体来一次性插入整个数组,或者使用Bulk操作来提高性能。

以下是两种优化方法:

方法1:使用Insert批量插入

package main

import (
    "log"
    "gopkg.in/mgo.v2"
)

type Indicator struct {
    // 根据你的数据结构定义字段
    ID   int    `bson:"_id"`
    Name string `bson:"name"`
}

func main() {
    session, err := mgo.Dial("localhost")
    if err != nil {
        panic(err)
    }
    defer session.Close()
    
    session.SetMode(mgo.Monotonic, true)
    c := session.DB("Test").C("Indicators")

    // 假设HeadDet是你的数据数组
    var HeadDet []Indicator
    
    // 使用Insert一次性插入整个切片
    err = c.Insert(HeadDet...)
    if err != nil {
        log.Fatal(err)
    }
}

方法2:使用Bulk操作(推荐用于大量数据)

package main

import (
    "log"
    "gopkg.in/mgo.v2"
)

func main() {
    session, err := mgo.Dial("localhost")
    if err != nil {
        panic(err)
    }
    defer session.Close()
    
    session.SetMode(mgo.Monotonic, true)
    c := session.DB("Test").C("Indicators")

    // 创建Bulk操作
    bulk := c.Bulk()
    
    // 假设HeadDet是你的数据数组
    var HeadDet []interface{} // 使用interface{}类型
    
    // 将所有文档添加到Bulk操作中
    for _, doc := range HeadDet {
        bulk.Insert(doc)
    }
    
    // 执行批量插入
    _, err = bulk.Run()
    if err != nil {
        log.Fatal(err)
    }
}

方法3:使用Unordered Bulk操作(性能最佳)

package main

import (
    "log"
    "gopkg.in/mgo.v2"
)

func main() {
    session, err := mgo.Dial("localhost")
    if err != nil {
        panic(err)
    }
    defer session.Close()
    
    session.SetMode(mgo.Monotonic, true)
    c := session.DB("Test").C("Indicators")

    // 创建无序Bulk操作(允许部分失败继续执行)
    bulk := c.Bulk()
    bulk.Unordered()
    
    var HeadDet []interface{}
    
    // 批量添加所有文档
    for _, doc := range HeadDet {
        bulk.Insert(doc)
    }
    
    // 执行批量操作
    _, err = bulk.Run()
    if err != nil {
        log.Fatal(err)
    }
}

使用Bulk操作可以显著提高插入大量数据的性能,因为它减少了网络往返次数和数据库操作的开销。对于数万条以上的数据,性能提升会非常明显。

回到顶部