MongoDB(Golang)常用复合查询

MongoDB(Golang)查询&修改

https://www.jianshu.com/p/b63e5cfa4ce5

>> 资源下载: https://72k.us/file/14896800-396374653

以下所有例子中结构定义如下:

type User struct {
    Id_ bson.ObjectId `bson:"_id"`
    Name string `bson:"name"`
    Age int `bson:"age"`
    JoinedAt time.Time `bson:"joined_at"`
    Interests []string `bson:"interests"
}

1、查询

通过func (c *Collection) Find(query interface{}) *Query来进行查询,返回的Query struct可以有附加各种条件来进行过滤。

通过Query.All()可以获得所有结果,通过Query.One()可以获得一个结果,注意如果没有数据或者数量超过一个,One()会报错。

条件用bson.M{key: value},注意key必须用MongoDB中的字段名,而不是struct的字段名。

1.1、查询所有

var users []User
c.Find(nil).All(&users)

上面代码可以把所有Users都查出来:

1.2、根据ObjectId查询

id := "5204af979955496907000001"
objectId := bson.ObjectIdHex(id)
user := new(User)
c.Find(bson.M{"_id": objectId}).One(&user)

更简单的方式是直接用FindId()方法:

c.FindId(objectId).One(&user)

注意这里没有处理err。当找不到的时候用One()方法会出错。

1.3、单条件查询

=($eq)

c.Find(bson.M{"name": "Jimmy Kuu"}).All(&users)

!=($ne)

c.Find(bson.M{"name": bson.M{"$ne": "Jimmy Kuu"}}).All(&users)

>($gt)

c.Find(bson.M{"age": bson.M{"$gt": 32}}).All(&users)

<($lt)

c.Find(bson.M{"age": bson.M{"$lt": 32}}).All(&users)

>=($gte)

c.Find(bson.M{"age": bson.M{"$gte": 33}}).All(&users)

<=($lte)

c.Find(bson.M{"age": bson.M{"$lte": 31}}).All(&users)

in($in)

c.Find(bson.M{"name": bson.M{"$in": []string{"Jimmy Kuu", "Tracy Yu"}}}).All(&users)

no in($nin)

同$in,

是否包含这个键($exists)

c.Find(bson.M{"name": bson.M{"$exists": true}}).All(&users)

查询键值为null的字段

c.Find(bson.M{"name": bson.M{"$in":[]interface{}{null}, "$exists": true}}).All(&users)

模糊查询($regex)

c.Find(bson.M{"name": bson.M{"$regex": "^[0-9]+"}}).All(&users)

$size

查询键值为长度是size的数组
c.Find(bson.M{"Interests": bson.M{"$size": 3}}).All(&users)

上面就是查询Interests数组长度为3的所有人

$all

查询数组中包含所有值得匹配(不分顺序,只看包含与否)

c.Find(bson.M{"Interests": bson.M{"$all": []string{"11","22","33"}}}).All(&users)

上面就是查询Interests中包含11,22,33的所有人

如果数组只有一项内容

c.Find(bson.M{"Interests": bson.M{"$all": []string{"11"}}}).All(&users)
c.Find(bson.M{"Interests": "11"}).All(&users)

以上结果一致

key.index
如果要查询数组指定位置

c.Find(bson.M{"Interests.2": "33"}).All(&users)

以上就是查询Interests的第二个元素为"33"的所有人

1.4、多条件查询

and($and)

c.Find(bson.M{"name": "Jimmy Kuu", "age": 33}).All(&users)

or($or)

c.Find(bson.M{"$or": []bson.M{bson.M{"name": "Jimmy Kuu"}, bson.M{"age": 31}}}).All(&users)

2、修改

通过func (*Collection) Update来进行修改操作。

func (c *Collection) Update(selector interface{}, change interface{}) error

注意修改单个或多个字段需要通过$set操作符号,否则集合会被替换。

2.1、($set)

修改字段的值

c.Update(
bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")},
bson.M{"$set": bson.M{ "name": "Jimmy Gu", "age": 34, }}
)

2.2、inc($inc)

字段增加值

c.Update(
bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")},
bson.M{"$inc": bson.M{ "age": -1, }}
)

2.3、push($push)

从数组中增加一个元素

c.Update(
bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")},
bson.M{"$push": bson.M{ "interests": "Golang", }}
)

2.4、pull($pull)

从数组中删除一个元素

c.Update(
bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")},
bson.M{"$pull": bson.M{ "interests": "Golang", }}
)

2.5、删除

c.Remove(bson.M{"name": "Jimmy Kuu"})

这里也支持多条件,参考多条件查询。

 

golang 使用mongo-go-dirver创建TTL索引, 过期自动删除数据

 sky_terra 

本文链接:https://blog.csdn.net/sky_terra/article/details/88357065

数据库:test_db, 数据表 test_table:

id

content

expire_date

1Good luck

2019-03-01 08:14:58.000

2Good luck

2019-03-02 08:14:58.000

3Good luck

2019-03-03 08:14:58.000

4Good luck

2019-03-04 08:14:58.000

5Good luck

2019-03-05 08:14:58.000

6Good luck

2019-03-06 08:14:58.000

示例代码:

client = mongo.Connect(...)
// mongo-go-driver v0.1.0 使用如下代码
indexModel := mongo.IndexModel{
Keys: bsonx.Doc{{"expire_date", bsonx.Int32(1)}}, // 设置TTL索引列"expire_date"
Options:mongo.NewIndexOptionsBuilder().ExpireAfterSeconds((1*24*3600)).Build(), // 设置过期时间1天,即,条目过期一天过自动删除
}
// mongo-go-driver v0.3.0 使用如下代码
indexModel := mongo.IndexModel{
Keys: bsonx.Doc{{"expire_date", bsonx.Int32(1)}}, // 设置TTL索引列"expire_date"
Options:options.Index().SetExpireAfterSeconds(1*24*3600), // 设置过期时间1天,即,条目过期一天过自动删除
}
_, err := client.Database("test_db").Collection("test_table").Indexes().CreateOne(context.Background(), indexModel) // 创建TTL
if err != nil {
// 出错处理
}
 

如果当前时间2019-03-02 08:15:58.000,则第一条记录就会被自动删除

 

>> 菜鸟教程: https://www.runoob.com/mongodb/mongodb-aggregate.html

MongoDB 聚合

MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。


aggregate() 方法

MongoDB中聚合的方法使用aggregate()。

语法

aggregate() 方法的基本语法格式如下所示:

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

实例

集合中的数据如下:

{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'runoob.com',
   url: 'http://www.runoob.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: 'NoSQL Overview', 
   description: 'No sql database is very fast',
   by_user: 'runoob.com',
   url: 'http://www.runoob.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j Overview', 
   description: 'Neo4j is no sql database',
   by_user: 'Neo4j',
   url: 'http://www.neo4j.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},

现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:

> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
{
   "result" : [
      {
         "_id" : "runoob.com",
         "num_tutorial" : 2
      },
      {
         "_id" : "Neo4j",
         "num_tutorial" : 1
      }
   ],
   "ok" : 1
}
>

以上实例类似sql语句:

 select by_user, count(*) from mycol group by by_user

在上面的例子中,我们通过字段 by_user 字段对数据进行分组,并计算 by_user 字段相同值的总和。

下表展示了一些聚合的表达式:

表达式描述实例
$sum计算总和。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg计算平均值db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min获取集合中所有文档对应值得最小值。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max获取集合中所有文档对应值得最大值。db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push在结果文档中插入值到一个数组中。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet在结果文档中插入值到一个数组中,但不创建副本。db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first根据资源文档的排序获取第一个文档数据。db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last根据资源文档的排序获取最后一个文档数据db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

管道的概念

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

这里我们介绍一下聚合框架中常用的几个操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。

管道操作符实例

1、$project实例

 

db.article.aggregate(
    { $project : {
        title : 1 ,
        author : 1 ,
    }}
 );

这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:

db.article.aggregate(
    { $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }});

2.$match实例

db.articles.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );

$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。

3.$skip实例

db.article.aggregate(
    { $skip : 5 });

经过$skip管道操作符处理后,前五个文档被"过滤"掉。

 

Ref:

https://docs.mongodb.com/manual/core/index-ttl/ TTL index详细介绍

https://docs.mongodb.com/manual/indexes/#index-types  IndexModel中关于index type的详细介绍

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一、为什么会做这个封装 提供CURD,事务等基础功能封装,提高开发效率: golang提供了很多的类库下载,但是并不方便直接使用,或者重复使用的方法没有基于业务层的封装,调用极其繁琐反复,笔者在使用时深有感受;故封装了连接池,数据库常用功能(增删改查,事务执行,管道聚合操作),并提供具体的使用和详细的demo,代码块注释和readme.txt文件中简要记录笔者从0-1的踩坑总结 二、这个目录涉及哪些主要包,提供哪些功能 基于Mgo,Mongo-go-driver这两个比较常用MongoDB基础库,做了连接池初始化,model层服务封装,提供:初始化MongoDB连接池复用, MongoDB集合(类似MySQL的数据表)的增、删、改、查,事务、管道操作、聚合操作、mongoShell原生命令执行、多表关联查询 等功能;另外明确一下,此包是笔者为了提供开发效率,基于上述基础库的二次功能封装,可能存在不足,如有异议,欢迎交流 三、使用本工具代码块,可以帮助到你什么 使用须知: 1. 首先本代码块是基于企业业务的封装,具有普遍使用性,涵盖了绝大部分应用场景 2. 适合MongoDB初学者:降低学习成本,底层实现对使用者透明,操作简单,提升开发效率 3. 适合从RDB(关系型数据库)刚转用MongoDB的使用者:此封装照顾了 MySQL等RDB使用者的用户习惯,返回的数据格式和ORM(关系映射数据格式)基本一致, 4. 照顾了 PHP 转 Golang的使用者,笔者以前也做过PHP,故使用过PHP的YII2,Laravel,ThinkPHP的开发者也能很清晰的看懂封装逻辑 5. 适合还未参加工作的同学,这些代码来自企业的基础功能包,是真实的工作代码 6. 本文件目录为功能代码块,可参考笔者的一篇MongoDB相关的博客使用,包含作者踩过的一些坑,可帮助初学使用者加深理解,内容涉及MongoDB相关(安装,常识,Mysql和MongoDB的基本对比,原生mongo shell命令...) 四、下载后,请先阅读readme.txt,如有异议,欢迎交流

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值