zoukankan      html  css  js  c++  java
  • Mongodb使用

    Mongodb基本的原则是:条件句是内层文档的键,修改器是外层文档的键【即,修改器要修改的字段声明在修改器内部】。
    1、$size,用于查询数组大小为size的记录

    db.a.find({"comments":{"$size":3}})
    表示查询comments数组中含有三个元素的记录。
    既然size可以查询指定数组大小的记录,那么,如果在文档中增加一个size字段,就可以使用 $gt和$lt等比较操作符来进行查询了。
    比如说我们增加了一个size字段,表示目前comments中含有的评论个数,那么在查询的时候就可以使用
    db.a.find({"size":{"$gt":3}})
    这样就能查询出来comment个数大于3个的了。
    记得维护size的数据哦,更新comments数据的时候,同时更新size字段
    db.a.update({},{"$push":{"cmt":"another comment!"},"$inc":{"size":1}})
    2、删除记录中的一个字段
    db.a.update({},{"$unset":{"addrs":1}})
    3、$push向数组中增加一个元素,如果数组不存在则创建
    db.a.update({},{"$push":{"addrs":"shenzhen"}})
    4、从数组中删除一个
    $pop
    db.a.update({},{"$pop":{"addrs":-1}})
    -1表示从数组末尾删除。
    db.a.update({},{"$pop":{"addrs":1}})
    1表示从数组头部删除
    $pull
    $pull可以删除指定的数组元素
    db.a.update({},{"$pull":{"addrs":"shenzhen"}})
    5、给已存在的对象增加一个键值或修改一个键值
    db.a.update({},{"$set":{"addrs":['shenzhen','guangzhou']}})
    6、查询一个数组的最前n、最后n个元素
    db.a.find({},{"addrs":{"$slice":5}})
    这里查询了一条记录中地址中的前5个。后5个可以用-5。并且,slice也支持偏移和要返回的数据量

    db.a.find({},{"addrs":{"$slice":[5,10]}})上面的语句查询了从第6条数据开始,一共10条数据,如果从第六条数据开始,后面不足10条,那么返回后面的所有元素。

    7、skip

    使用Mongodb的时候【其他数据库也类似】,尽量少跳过过多的数据,这样会产生性能问题。
    mongodb的skip是用来跳过数据的,但是要少用。需要使用的时候可以用其他方式代替。比如说要对博客文章分页,那么一般的做法是
    db.a.find().sort({"time":1}).skip(10000).limit(10)
    优化的做法可能是,根据上一页取出来的时间,在下次分页,即取出下一页的时候,根据上一个时间,来查找,然后再limit,例如
    db.a.find({"time":{"$gt":lasttime}}).sort({"time":1})..limit(10)
    这样用查找替代跳过数据,效率会有提升。

    8、有一个需求是从一个collection中随机选取出一个文档。

    那么一般的做法是,先统计文档总数count,然后生成一个1到count的数字,去数据库中取出这个数字对应的文档。

    这种方法是很低效的。要统计count,然后才能取出来数据。

    高效的做法是:在存储数据的时候,同时存储一个random字段。
    每次插入一个记录的时候,都生成一个随机数字赋值给这个字段。那么在随机选取一个文档的时候,这样就可以生成一个随机数rand,然后找到比这个随机数大的一个文档:
    result=db.a.findOne({"random":{"$gt":rand}})
    if result == null
        result=db.a.findOne({"random":{"$gt":rand}})

    这样如果最后result还是null,说明数据库中是没有记录了。随机取出一个文档的任务也完成了。

    9、删除索引

    db.a.dropIndex("indexname")

    其中的indexname可以在system.index集合中查找。

    10、查询内嵌文档

    例如有如下文档:

    {"content":"this is content","comments":[{"author":"naughty","score":3},{"author":"cc","score":4}]}

    现在要查询author是naughty并且naughty的评论score大于3的记录,那么首先想到的查询是这样的:

    db.a.find({'comments.author':'naughty'},{'comments.score':{$gt:3}})

    但是记录多起来,查询的时候会发现,这样写是不对的。这样写,只要comments中有naughty并且有score是大于3,那么就会查询出来这条记录。查询结果不是我们想要的。

    “要正确的指定一组条件,而不是单独的指定每个键。”书上如是说。

    要这样写查询:

    db.a.find({"comments":{"$elemMatch":{"author":"naughty","score":{"$gt":3}}}})这样就对了。

    elemMatch将限定条件进行分组,仅当需要对一个内嵌文档的多个键进行查询的时候,才会用到。

    11、group

    假设有类似的一个需求:

    有几条这样的文档

    db.d.insert({"day":"2012-9-9","tags":['a','b','c','d']})
    db.d.insert({"day":"2012-9-9","tags":['c','d']})
    db.d.insert({"day":"2012-9-9","tags":['a','d']})
    db.d.insert({"day":"2012-9-10","tags":['a','b']})
    db.d.insert({"day":"2012-9-10","tags":['a','d']})

    要查询每一天tags中出现次数最多的那个tag是什么。那么查询可以按照如下进行:

    db.d.group({"key":{"day":true},"initial":{"tags":{}},"reduce":function(doc,res){
        for(i in doc.tags){
            if(doc.tags[i] in res.tags){
                res.tags[doc.tags[i]]++;
            }else{
                res.tags[doc.tags[i]]=1;
            }
        }
    },
    "finalize":function(res){
        var mp=0;
        for(i in res.tags){
            if(res.tags[i]>mp){
                res.tag=i
                mp=res.tags[i];
            }
        }
        delete res.tags
    }
    })

    其中finalize是在group动作结束之后,对聚合的每一个组调用一次。reduce函数是在聚合的时候进行调用,是用来生成分组的。reduce函数的两个参数分别是:当前文档和本组当前的聚合结果。

    12、分片

    分片【sharding】的目的是为了提高存储性能,那么什么时候进行分片呢?

    第一、机器磁盘不够用了。

    第二、机器已经不能满足写数据的性能需求。

    第三、想把大数据都放在内存中以提高性能。

    mongos就是mongodb的各个版本中都配备的路由器进程,它路由所有的请求,然后将结果聚合。它本身并不存储数据或者是配置信息(但是会缓存配置服务器的信息)。配置服务器存储了集群的配置信息:数据和片的对应关系。

  • 相关阅读:
    java ElasticSearch并发操作之乐观锁的使用
    ES并发更新导致冲突的问题
    012 found ' ' @ line 30, column 50. 'com.google.code.gson:gson:2.7
    011 Error:Failed to resolve: com.android.support:recyclerview-v7:28.0.0解决方法
    010 Failed to resolve: com.squareup.okhttp3:okhttp:3.4.1
    009 A problem occurred configuring project ':app'. > Failed to notify project evaluation listener. >
    008 导入项目每次都要Gradle:Download https://services.gradle.org/distributions/gradle
    007 Android Studio错误Error:(23, 17) 解决方案
    006 Unable to tunnel through proxy. Proxy returns "HTTP/1.1 400 Bad Request"解决办法
    005 Android Studio 快捷键大全
  • 原文地址:https://www.cnblogs.com/DjangoBlog/p/3966202.html
Copyright © 2011-2022 走看看