美文网首页
Mongo入门

Mongo入门

作者: IT5 | 来源:发表于2018-12-04 15:22 被阅读13次

    什么是MongoDB

    MySQL

    memory 内存引擎

    NoSQL最大的特点:
    默认支持分布式(内置分布式解决方案)
    高性能,高可用性和可伸缩性

    在NoSQL界,
    MongoDB是一个最像关系型数据库的非关系型数据库

    MongoDB应用场景
    适用范围
    1)网站实时数据: 例如:日志、Timeline、用户行为(代替方案:用日志)
    2)数据缓存:缓存的数据,它一定是临时的 (关系型数据有一份已经持久化)
    3)大尺寸、低价值数据存储: 搜索引擎的图片文件、视频文件(结构化),
    一份存磁盘、一份存Mongo
    4)高伸缩性场景:机器可以任意的增减
    5)对象或JSON数据存储: 完全可以选择用Redis

    不适用范围
    1)高度事务性系统: 例如:金融系统的核心数据
    高机密的用户数据(只能选择传统关系型数据库)

    2)传统的商业智能应用:结构化查询要求非常高,经常做关联查询统计
    (如果都是单表查询,用Java程序来实现关联)
    Map,List (id_az_a)

    MongoDB 4.0 支持事务操作(分布式事务的一种解决方案)

    java简单操作mongoDB
    2.连接Mongo
    2.1.无用户名密码验证

    //连接"localhost:27017"可以直接使用无参构造new MongoClient();
    MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
    

    2.2.需要用户名密码验证

    //连接到MongoDB服务 如果是远程连接可以替换“localhost”为服务器所在IP地址  
    //ServerAddress()两个参数分别为 服务器地址 和 端口  
        ServerAddress serverAddress = new ServerAddress("localhost",27017);  
        List<ServerAddress> addrs = new ArrayList<ServerAddress>();  
        addrs.add(serverAddress);  
    //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码  
       MongoCredential credential = MongoCredential.createScramSha1Credential("username",   "databaseName", "password".toCharArray());  
       List<MongoCredential> credentials = new ArrayList<MongoCredential>();  
       credentials.add(credential);  
    
    

    //通过连接认证获取MongoDB连接

    MongoClient mongoClient = new MongoClient(addrs,credentials);
    

    3.获取操作数据库/不存在会创建

    MongoDatabase db = mongoClient.getDatabase("mydb");
    

    4.创建集合
    Mongo中的集合,可以看做是数据库中的表。

    db.createCollection("user");
    

    5.获得指定集合,并遍历所有数据

    MongoCollection<Document> users = db.getCollection("user");
    FindIterable<Document> documents = users.find();
    for (Document document : documents) {
        System.out.println(document);
    }
    

    6.查询
    6.1 通过Document查询条件
    //查找所有name = csc的document

    Document query1 = new Document("name", "csc");
    FindIterable<Document> documents = users.find(query1);
    for (Document d : documents) {
        System.out.println(d.toJson());
    }
    使用运算符“$lt”,"$gt","$lte","$gte"
    //age < 25
    Document query2 = new Document("age", new Document("$lt", 25));
    FindIterable<Document> documents = users.find(query2);
          
    and连接多个条件
    
    Document query3 = new Document("age", new Document("$lt", 25)).append("name", "csc");
    FindIterable<Document> documents = users.find(query3);  
    也可以:
    Document query4 = new Document("name", "csc");
    query4.put("age", new Document("$lt", 25));
    FindIterable<Document> documents = users.find(query4);
           
    or连接多个条件
    
    //name = csc || name == dqr
    Document query5 = new Document("$or", Arrays.asList(new Document("name", "csc"), new Document("name", "dqr")));
    FindIterable<Document> documents = users.find(query5);
           
    between...and...
    
    //如果这样写,会值返回age > 20的document,因为后面一个key为"age"的把前面一个覆盖了。
    Document query6 = new Document("age", new Document("$lt", 23)).append("age", new Document("$gt", 20));
    FindIterable<Document> documents = users.find(query6);
    //正确写法:
    Document query6 = new Document("age", new Document("$lt", 23).append("$gt", 20));
    FindIterable<Document> documents = user.find(query6);     
    

    6.2 通过Filters指定查询条件(更简洁的做法)
    相等:eq

    FindIterable<Document> documents = user.find(Filters.eq("name", "csc"));
    

    不等:ne、lt、lte、gt、gte

    FindIterable<Document> documents = user.find(Filters.lte("age", 23));
    

    in:

    FindIterable<Document> documents = user.find(Filters.in("age", Arrays.asList(23,25,27)));
    

    and:

    Bson and = Filters.and(Filters.eq("name", "csc"), Filters.ne("age", 25));
    FindIterable<Document> documents = user.find(and);
    

    or:

    FindIterable<Document> documents = user.find(Filters.or(Filters.eq("age",23),Filters.eq("age", 25)));         
    

    6.3 count
    l

    ong cnt = user.count(Filters.eq("age", 27));
    System.out.println(cnt);
    

    6.4 sort
    //按name升序

    FindIterable<Document> documents = user.find().sort(Sorts.ascending("name"));
    //按age将序
    FindIterable<Document> documents = user.find().sort(Sorts.descending("age"));
    //按name升序,name相同的按age降序
    FindIterable<Document> documents = user.find().sort(Sorts.orderBy(Sorts.ascending("name"), Sorts.descending("age")));
    

    6.5 skipe & limit
    //跳过前5条(0-4),返回(5-9)共5条。

    FindIterable<Document> documents = user.find().sort(Sorts.descending("age")).skip(5).limit(5);
    

    6.6 distinct

    DistinctIterable<String> name = user.distinct("name", String.class);
    DistinctIterable<Integer> age = user.distinct("age", Integer.class);
    for (Integer a : age) {
        System.out.println(a);
    }
    for (String s : name) {
        System.out.println(s);
    }
    

    7.添加document
    7.1添加单个document

    Document doc = new Document();
    doc.put("name", "zhangsan");
    doc.put("age", 40);
    user.insertOne(doc);
    

    7.2添加多个文档

    List<Document> docs = new LinkedList<Document>();
    for(int i=0; i<10; i++){
        Document doc = new Document();
        doc.put("name", "zhangsan"+i);
        doc.put("age", 40+i);
        docs.add(doc);
    }
    user.insertMany(docs);
    

    8.修改document
    updateOne/updateMany:

    user.updateMany(Filters.eq("age", 25), new Document("$set", new Document("age", 16).append("name","xxx25")));
    

    9.删除document
    deleteOne/deleteMany:

    //删除第一个符合条件的
    user.deleteOne(Filters.eq("age", 17));
    //删除所有符合条件的
    user.deleteMany(Filters.eq("age", 17));
    

    10.aggregate
    以流水线的方式,分阶段处理document。

    主要阶段:
    $project
    对流入的每个document进行投影操作,类似于select field1, field2, ...
    可以添加新字段、或删除已存在的某些字段。

    MongoClient mongo = new MongoClient();
    MongoDatabase db = mongo.getDatabase("test");
    MongoCollection<Document> hobby = db.getCollection("student");
    hobby.insertOne(new Document("name", "csc").append("hobby", Arrays.asList("reading", "coding")));
    hobby.insertOne(new Document("name", "nicky").append("hobby", Arrays.asList("game")));
    hobby.insertOne(new Document("name", "jack").append("hobby", Arrays.asList("movie")));
    hobby.insertOne(new Document("name", "tom").append("hobby", Arrays.asList("reading", "coding")));
    hobby.insertOne(new Document("name", "lucy").append("hobby", Arrays.asList("reading", "football")));
    hobby.insertOne(new Document("name", "lion").append("hobby", Arrays.asList("basketball", "football")));
    AggregateIterable<Document> aggregate = hobby.aggregate(Arrays.asList(new Document("$project", new Document("name", 1).append("_id", 0).append("hobby", 1))));
    for (Document document : aggregate) {
        System.out.println(document.toJson());
    } 
    

    只有_id默认输出的,不想输出该字段,需要设置为0,需要输出的其他字段需要手动设置为1.
    输出结果:

    { "name" : "csc", "hobby" : ["reading", "coding"] }
    { "name" : "nicky", "hobby" : ["game"] }
    { "name" : "jack", "hobby" : ["movie"] }
    { "name" : "tom", "hobby" : ["reading", "coding"] }
    { "name" : "lucy", "hobby" : ["reading", "football"] }
    { "name" : "lion", "hobby" : ["basketball", "football"] } 
    

    $match
    类似于where字句

    AggregateIterable<Document> aggregate = hobby.aggregate(Arrays.asList(
                new Document("$project", new Document("name",1).append("_id", 0).append("hobby", 1))
                ,new Document("$match", new Document("name", "csc"))
        )); 
    

    输出结果:

    { "name" : "csc", "hobby" : ["reading", "coding"] }
    

    limit &skip同上面的用法
    $unwind
    把数组中的元素拆分为多个document。

    AggregateIterable<Document> aggregate = hobby.aggregate(Arrays.asList(
                new Document("$project", new Document("name", 1).append("_id", 0).append("hobby", 1))
                ,new Document("$unwind", "$hobby")
        ));
    

    输出结果:

    { "name" : "csc", "hobby" : "reading" }
    { "name" : "csc", "hobby" : "coding" }
    { "name" : "nicky", "hobby" : "game" }
    { "name" : "jack", "hobby" : "movie" }
    { "name" : "tom", "hobby" : "reading" }
    { "name" : "tom", "hobby" : "coding" }
    { "name" : "lucy", "hobby" : "reading" }
    { "name" : "lucy", "hobby" : "football" }
    { "name" : "lion", "hobby" : "basketball" }
    { "name" : "lion", "hobby" : "football" }
    

    group 类似于group by,可以使用各种聚合操作符,常用的有:sum, avg,max, min,first, $last
    //计算每个hobby的人数

    AggregateIterable<Document> aggregate = hobby.aggregate(Arrays.asList(
                new Document("$project", new Document("name", 1).append("_id", 0).append("hobby", 1))
                ,new Document("$unwind", "$hobby")
                ,new Document("$group", new Document("_id", "$hobby").append("count", new Document("$sum", 1)))
        ));
    

    必须首先设置("_id", "hobby"),这句的含义是group by hobby这个字段。引用字段一定要添加打头。
    如:输出每个hobby的第一个name: ("fisrt","name")。

    AggregateIterable<Document> aggregate = hobby.aggregate(Arrays.asList(
                new Document("$project", new Document("name", 1).append("_id", 0).append("hobby", 1))
                ,new Document("$unwind", "$hobby")
                ,new Document("$group", new Document("_id", "$hobby").append("count", new Document("$sum", 1)).append("first", new Document("$first", "$name")))
        ));
    

    输出结果:

    { "_id" : "basketball", "count" : 1, "first" : "lion" }
    { "_id" : "football", "count" : 2, "first" : "lucy" }
    { "_id" : "movie", "count" : 1, "first" : "jack" }
    { "_id" : "game", "count" : 1, "first" : "nicky" }
    { "_id" : "coding", "count" : 2, "first" : "csc" }
    { "_id" : "reading", "count" : 3, "first" : "csc" }
    

    11.mapreduce
    map function

    function() {
       ...//自定义操作
       emit(key, value);
    }
    

    文档中的说明:

    In the map function, reference the current document as this within the function.
    The map function should not access the database for any reason.
    The map function should be pure, or have no impact outside of the function (i.e. side effects.)
    A single emit can only hold half of MongoDB’s maximum BSON document size.
    The map function may optionally call emit(key,value) any number of times to create an output document associating key with value.
    reduce function
    function(key, values) {
       ...//自定义操作
       return result;
    }
    

    文档中的说明:

    The reduce function should not access the database, even to perform read operations.
    The reduce function should not affect the outside system.
    MongoDB will not call the reduce function for a key that has only a single value. The values argument is an array whose elements are the value objects that are “mapped” to the key.
    MongoDB can invoke the reduce function more than once for the same key. In this case, the previous output from the reduce function for that key will become one of the input values to the next reduce function invocation for that key.
    The reduce function can access the variables defined in the scope parameter.
    The inputs to reduce must not be larger than half of MongoDB’s maximum BSON document size. This requirement may be violated when large documents are returned and then joined together in subsequent reduce steps.
    

    mapreduce demo
    //统计每个年龄的人数,原理同hadoop中的map、reduce方法。
    //定义一个js function,以年龄作为key,进行计数。this表示当前document

    String map = "function(){emit(this.age, 1)}";//age : [1,1,1,1]
    //js function, 对年龄的所有计数,累加返回key-value
    String reduce = "function(key, values){ return Array.sum(values)}";
    MapReduceIterable<Document> docs = user.mapReduce(map, reduce);
    for (Document doc : docs) {
        System.out.println(doc.toJson());
    }
    

    转载自:http://www.cnblogs.com/dqrcsc/p/6031389.html
    确实写的很不错! 所以收集一下该文章了

    相关文章

      网友评论

          本文标题:Mongo入门

          本文链接:https://www.haomeiwen.com/subject/jhgmcqtx.html