mongoDB的更新无重复+子文档+分页查询
很多朋友在使用mongoDB的过程中会有各种各样的疑问。比如:如何提高mongoDB更新效率?在mongoDB中如何实现对子文档(数组等方式存储)的分页查询等
本文就针对这些零散的功能点进行一个整理,并做成一个实现demo供大家参考。
一、首先了解下mongoDB的更新,mongoDB的更新方式有2大类:save()和update()
官方更新方法的说明:https://www.runoob.com/mongodb/mongodb-update.html
这里需要使用的是update()类的更新方式:
mongoDB的优势在于查询快,所有的数据都是单文档形式保存,数据量上很多都是上千万甚至上十亿条记录,有些复杂的文档中会含有数组形式子文档内容,(一般都是结构相同的多条数据)。当业务需要对该文档中的子文档做记录追加时,如果单纯进行save()或者update()操作,都会引起全文当的更新。:
1.初步方法选择:大类中我们选择使用update()更新方式
插入初始数据结构:
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "123"
}
]
}
save():是重新创建一个新的document文档替换现有的ducument文档,
update():是在原有文档上直接更新字段内容如(可提高效率,但存在一定问题,下面具体分析):
插入:"comments" : [ { "num1" : "124"}]。
插入后希望得到的结果:
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "123"
},
{
"num1" : "124"
}
]
}
使用update(),原有字段"comments" : [ { "num1" : "123"}] ,更新后则为:"comments" : [ { "num1" : "124"}]
实际结果:
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "124"
}
]
}
此文首先要明确的是希望我们可以在comments字段下更新后有两条记录:"comments" : [ { "num1" : "123"},{ "num1" : "124"}]
因此单纯使用update()方式不能完全适用,那么进行下一步的更新方法优化。
2。$push的使用可以实现在子文档数组中追加记录的功能:
db.getCollection.update({_id:"1.ch"},{$push:{comments:[{"num1":"124"}]}})
第一次操作后:"comments" : [ { "num1" : "123"},{ "num1" : "124"}] 结果为:
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "123"
},
{
"num1" : "124"
}
]
}
但是如果重复此操作时,记录会重复插入相同记录(无下限)
"comments" : [ { "num1" : "123"},{ "num1" : "124"},{ "num1" : "124"},{ "num1" : "124"},{ "num1" : "124"}] :
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "123"
},
{
"num1" : "124"
},
{
"num1" : "124"
},
{
"num1" : "124"
},
{
"num1" : "124"
}
]
}
这依然不能实现本例中需要的更新但不重复更新的要求(多批次更新数据为避免数据遗漏会有数据冗余,但相同记录不需要做重复插入或更新操作)。因此还需要我们对update()方法做进一步的选取
3.$addToSet:数组中存在记录则不作更新,反之进行插入更新:
db.getCollection.update({_id:"1.ch"},{$addToSet:[{"num1":"124"}]}})
第一次操作后:"comments" : [ { "num1" : "123"},{ "num1" : "124"}],
重复操作后的结果依然是:"comments" : [ { "num1" : "123"},{ "num1" : "124"}]
因此我们对数据更新操作的语句选取为update({_id:"1.ch"},{$addToSet:[{"num1":"124"}]}})。
现在数据已经有了最佳的更新方式,接下来要做的就是当数组文档如何实现分页查询,并且在查询时还能保证mongoDB依然高效。
二、索引的选取
在这里首先要考虑一个问题。百万级别以上的数据是怎样的结构。
例如:
第一种情况:一共有一千万条流水记录分别是是个账户的流水,那么每个账号的流水都有百万级别。此时需要选取的索引更多的考虑使用联合索引。
第二种情况:同样有一千万条流水记录,但是账户有几十万甚至上百万,而每个账户下的流水最多不超过1万条。那么此时选择的索引仍然使用唯一索引(_id)即可,因为这样的数据查询响应时间仍能保证毫秒级别的响应速度。
三:分页查询
选取好索引后我们开始进行数组子文档的分页查询:
插入一条数据做测试:
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "123",
"num2" : "00R33",
"date" : "2020-01-16 : 14:32:00",
"flag" : "2"
},
{
"num1" : "124",
"num2" : "00R34",
"date" : "2020-01-16 : 14:32:00",
"flag" : "2"
},
{
"num1" : "125",
"num2" : "00R35",
"date" : "2020-01-16 : 14:32:00",
"flag" : "1"
},
{
"num1" : "126",
"num2" : "00R36",
"date" : "2020-01-16 : 14:32:00",
"flag" : "1"
}
]
}
使用分页查询语句:
db.getCollection.find({_id:"1.ch"},{"comments":{ "$slice":[0,2]}})
查询结果:
{
"_id" : "1.ch",
"no" : "1"
"company" "ch"
"name" : "小明",
"comments" : [
{
"num1" : "123",
"num2" : "00R33",
"date" : "2020-01-16 : 14:32:00",
"flag" : "2"
},
{
"num1" : "124",
"num2" : "00R34",
"date" : "2020-01-16 : 14:32:00",
"flag" : "2"
}
]
}
comments:是需要做分页的子文档,{ "$slice":[0,2]}做分页查询,0是开始位置,2是查询条数
以上是自己的实操心得,欢迎大家留言讨论mongoDB的使用,提高能力