zoukankan      html  css  js  c++  java
  • 初入MongoDB

    初入MongoDB

    业务需求,需要用到MongoDB。向来一直是mysql数据库的思想,一下转换为nosql还是很不适应。经过一个月的开发,写一下自己的感触。本文会对应mysql数据库进行说明。

    数据库类型

    文档型数据库:存储的数据是非结构化数据。文档存储一般用类似 json 的格式存储,存储的内容是文档型的。

    相比mysql来说,mysql的表是高度结构化的,若添加字段可能需要修改表结构。MongoDB的话没有这个烦恼,在其中的每条数据可以认为一个“文档”。比如,一篇文章+评论,它可以存储为一个json,囊括了所有的信息,直接存入数据库。并且可以动态的横向扩展,不用担心字段不存在的问题。

    结构对比

    关系型数据库术语/概念 MongoDB 术语/概念 解释/说明
    Database Database 数据库
    Table Collection 数据库表/集合
    Row Document 数据记录行/文档
    Column Field 数据列/数据字段
    Index Index 索引
    Table joins 表关联/MongoDB 不支持(可以使用聚合查询)
    Primary Key Object ID 主键/MongoDB 自动将_id 设置为 主键

    接下来介绍一下项目中遇到的查询,以nodejs为例

    使用 & 高级查询

    基本查询

    //分页排序参数
    let opt = {
        sort: {username: 1},
        skip: (value.pageNum - 1) * value.pageSize,
        limit: value.pageSize,
    }
    //条件
    let query = {status: {$ne: -1}}
    if (params.keyWords) {
        //正则表达式
        let reg = new RegExp(value.keyWords)
        query['$or'] = [
            {nickname: reg},
            {phone: reg},
        ]
    }
    let admins = await AdminModel.getByQuery(query, '', opt)
    let admin = await AdminModel.getOneByQuery(query)
    

    查询方法

    //查询多条
    getByQuery(query, fileds, opt) {
        return this.model.find(query, fileds, opt).exec();
    }
    //查询单条
    getOneByQuery(query, fileds, opt) {
        return this.model.findOne(query, fileds, opt).exec();
    }
    //数量查询
    countByQuery(query) {
        return this.model.countDocuments(query)
    }
    //更新
    update(conditions, update, options) {
        return this.model.updateMany(conditions, update, options);
    }
    //去重查询
    distinct(query, field) {
        return this.model.find(query).distinct(field);
    }
    //保存
    save(model) {
        model = model instanceof this.model ? model : new this.model(model);
        return model.save();
    }
    //更新
    update(conditions, update, options) {
        return this.model.updateMany(conditions, update, options);
    }
    

    关联查询

    有时候由于业务的需要,需要关联查询。例如,查询某部门的信息,需要带有相应的负责人。

    这里呢,需要在dept(部门表)中添加相应用户表(user)表的objectId,就是MongoDB生成的_id

    const Schema = Model.SchemaExt({
        // userId为字段名称,ref中的“user” 代办表名
        userId: {type: ObjectId, ref: "user"},     // 负责人
        code: {type: String, required: true, unique: true},  // 部门编号
        name: {type: String, required: true},	             // 部门名称
        //...
    })
    

    这样的话,我们可以使用聚合查询查询出相关数据

    //这里的populate,代表的是字段名称
    getByIdPopulate(id, populate) {
        return this.model.findOne({_id: id}).populate(populate).exec();
    }
    

    查询结果

    {
        code: 001
        name: 山东分部
        userId: {
    		_id: xxxxx,
        	username: xx,
        	phone: xxx
    	}
    }
    

    聚合查询

    这样引申出另外一个问题,如果我需要根据手机号查找部门呢

    let listedModel = await deptModel.aggregate([
        //关联表,form需要关联的表,localField自己的字段,foreignField关联到表的字段,as关联出的内容key
        {
            $lookup: {
                from: "admins",
                localField: "admin",
                foreignField: "_id",
                as: "adminDetail"
            }
        }, {
            $unwind: '$adminDetail'
        }, {
            //查询条件,这里query = {'adminDetail.phone': xxx}
            $match: query,
        }, {
            //分页
            $facet: {
                data: [{
                    $sort: opt.sort
                }, {
                    $skip: opt.skip
                }, {
                    $limit: opt.limit
                }],
                count: [{
                    $group: {
                        _id: "count",
                        total: {$sum: 1}
                    },
                }]
            }
        }
    ])
    
  • 相关阅读:
    【MyBatis】学习笔记010--#{}与¥{}的区别
    【MyBatis】学习笔记009--基于注解的CRUD
    【MySQL】limit语法
    【MyBatis】学习笔记008--分页查询
    【MyBatis】学习笔记007--日志工厂
    【MyBatis】学习笔记006--resultMap简单结果映射
    【MyBatis】学习笔记005--生命周期与作用域
    【MyBatis】学习笔记004--XML配置
    重学动态规划
    剑指 Offer 09. 用两个栈实现队列
  • 原文地址:https://www.cnblogs.com/somliy/p/13652793.html
Copyright © 2011-2022 走看看