使用Golang和mgo从MongoDB集合中获取元素。

huangapple go评论77阅读模式
英文:

Getting the elements from Collection MongoDB using Golang and mgo

问题

我的任务是编写一个带有历史记录的聊天功能。为了创建历史记录,我需要将每条消息发送到MongoDB,并在下次连接时获取所有消息,并使用循环将其发送给连接到聊天的所有客户端。

这是我的ChatServer代码:

func ChatServer(ws *websocket.Conn) {

	// 连接到MongoDB,集合为History
	session, err := mgo.Dial("mongodb://******:*******@ds045795.mongolab.com:45795/catalog")
	if err != nil {
		panic(err)
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)
	c := session.DB("catalog").C("History")

	// fmt.Println(c.Find())
	// 将客户端添加到映射中
	clientId := ws.RemoteAddr().String()
	defer ws.Close()
	clients[ws] = true

	// 循环接收消息
	for {
		var msg string
		// 如果无法读取消息-从映射中删除客户端
		if err := websocket.Message.Receive(ws, &msg); err != nil {
			delete(clients, ws)
			return
		}
		sendAll(msg)
		err = c.Insert(&Connect{clientId, msg})
		if err != nil {
			log.Fatal(err)
		}
	}
}

所以,我的问题是如何按顺序从集合中获取所有元素。我不知道如何做到这一点,因为在文档中找不到合适的函数。也许你有其他的建议吗?

英文:

My task is writing chat with history. So for creating history i need each of messages send to Mongodb and when I have a next connecting I need to getting all messages and, with loop, send to all clients that are connected to chat

This is code of my ChatServer

func ChatServer(ws *websocket.Conn) {

// Connecting to MongoDB, collection History
session, err := mgo.Dial("mongodb://******:*******@ds045795.mongolab.com:45795/catalog")
if err != nil {
	panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB("catalog").C("History")

// fmt.Println(c.Find())
// Adding clients to the map
clientId := ws.RemoteAddr().String()
defer ws.Close()
clients[ws] = true

// Loop for receiving msg
for {
	var msg string
	// If can not read msg - delete client from map
	if err := websocket.Message.Receive(ws, &msg); err != nil {
		delete(clients, ws)
		return
	}
	sendAll(msg)
	err = c.Insert(&Connect{clientId, msg})
	if err != nil {
		log.Fatal(err)
	}
}
}

So my problem is getting all the elements in order from the collection.
I have no idea how to do it, because can not find the proper function in documentations.
Maybe you have some other offers?

答案1

得分: 0

首先,我同意上面评论者的观点 - 你应该在你的Connect结构中添加时间戳。但即使没有时间戳,你仍然可以通过ObjectID对条目进行排序,因为它的一部分是时间戳。是的,这种方法可能有些不太规范,并且如果你使用分片或将数据库转移到另一台服务器上可能会引发问题,但在你的情况下(单个Mongolab实例),你可以使用类似以下的代码实现(我不知道你的结构,所以"ip"和"message"只是假设):

var connects []Connect
c.Find(bson.M{"ip": "127.0.0.1"}).Sort("-_id").Limit(50).All(&connects) // 按降序获取50个条目

for _, connect := range connects {
    log.Println(connect.Message)
}

但是,真正的解决方法是在你的Connect结构中添加时间字段,像这样:

package main

import (
    "fmt"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "log"
    "time"
)

type Connect struct {
    Ip      string
    Message string
    Ts      time.Time
}

func main() {
    session, err := mgo.Dial("mongodb://souser:123456@ds055855.mlab.com:55855/catalog")

    if err != nil {
        panic(err)
    }
    defer session.Close()
    session.SetMode(mgo.Monotonic, true)

    c := session.DB("catalog").C("History")

    for i := 0; i < 100; i++ {
        c.Insert(&Connect{"127.0.0.2", fmt.Sprintf("Test message #%d", i), time.Now()})
        if err != nil {
            log.Fatal(err)
        }
    }

    var connects []Connect
    c.Find(bson.M{"ip": "127.0.0.2"}).Sort("-ts").Limit(50).All(&connects)

    for _, connect := range connects {
        log.Println(connect.Message)
    }
}

这样,你就可以通过时间字段进行排序和限制查询结果了。

英文:

First of all I agree with commenters above - you should add timestamp to your Connect structure. But even without it you can sort your entries by ObjectID as part of it is timestamp. Yes this is quite dirty way and may cause issues if you use sharding or transfer database to another server but in your case (single Mongolab instance) it's possible with something like like (I don't know your structure so "ip" and "message" are just assumptions)

var connects []Connect
c.Find(bson.M{&quot;ip&quot;: &quot;127.0.0.1&quot;}).Sort(&quot;-_id&quot;).Limit(50).All(&amp;connects) // 50 entries in desc order

for _, connect := range connects {
	log.Println(connect.Message)
}

But really add time to your Connect like that

package main

import (
	&quot;fmt&quot;
	&quot;gopkg.in/mgo.v2&quot;
	&quot;gopkg.in/mgo.v2/bson&quot;
	&quot;log&quot;
	&quot;time&quot;
)

type Connect struct {
	Ip      string
	Message string
	Ts      time.Time
}

func main() {
	session, err := mgo.Dial(&quot;mongodb://souser:123456@ds055855.mlab.com:55855/catalog&quot;)

	if err != nil {
		panic(err)
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)

	c := session.DB(&quot;catalog&quot;).C(&quot;History&quot;)

	for i := 0; i &lt; 100; i++ {
		c.Insert(&amp;Connect{&quot;127.0.0.2&quot;, fmt.Sprintf(&quot;Test message #%d&quot;, i), time.Now()})
		if err != nil {
			log.Fatal(err)
		}
	}

	var connects []Connect
	c.Find(bson.M{&quot;ip&quot;: &quot;127.0.0.2&quot;}).Sort(&quot;-ts&quot;).Limit(50).All(&amp;connects)

	for _, connect := range connects {
		log.Println(connect.Message)
	}
}

huangapple
  • 本文由 发表于 2016年2月27日 23:29:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/35671597.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定