要是你已经写了多少个调用API的demo,约等于说通过mongoose的model取回来的笔录中

1. 难题源于


近年来在落成多个API,当中有一对功效是内需从Mongodb中取出一个由Date对象组成的数组,然后将客户端传过来的unixtime合并到该数组中,并且去重新。

譬如,要是从mongodb中取回来的数目中有1个叫做gaming的项,专门用来记录用户进入娱乐的始发时间和剥离时间。
那么mongoose的schema的定义将大概是这么的:

const DeviceLogSchema = new Schema({
 ...
  gaming: [{ enter: Date, exit: Date, _id: false }],          
 ... 
});

而从mongodb取回来的数码大概就是以此样子的:

{
"gaming": [
      {
        "enter": 2017-04-25T14:32:12.081Z,
        "exit": 2017-04-25T14:48:52.082Z,
      },
      {
        "enter": 2017-04-26T14:32:12.081Z,
        "exit": 2017-04-26T14:48:52.082Z,
      }
    ],
}

约等于说通过mongoose的model取回来的记录中,enter和exit都是Date(对mongodb来说)类型的,而对此js来说,正是3个Object(js将全体不难类型以外的数据类型都处理成Object)。

let deviceLog = await DeviceLog.findOne({});
console.log(typeof deviceLog.enter) // ->Object

而客户端每隔一段时间就会调用api来将新的用户游戏时间回传给服务器,但用的格式是unixtime。

{
    "gaming": [{
      "enter": 1493130733081,
      "exit": 1493131734082,
    },{
      "enter": 1493130735084,
      "exit": 1493131736087,
    }],
}

此地的enter和exit的unixtime时间格式,对于js来说,便是number类型的。

咱俩因而mongoose来保存的时候,不需求将unixtime举办别的转换,直接保存,
mongoose会将其自行转成Date格式实行保存。也正是说,要是保留前的gaming内容是之类那个样子的:

"gaming": [
      {
        "enter": 2017-04-25T14:32:12.081Z,
        "exit": 2017-04-25T14:48:52.082Z,
      },
      {
        "enter": 2017-04-26T14:32:12.081Z,
        "exit": 2017-04-26T14:48:52.082Z,
      },
      {
        "enter": 1493130733081,
        "exit": 1493131734082,
      },
      {
        "enter": 1493130735084,
        "exit": 1493131736087,
      }
    ],

那正是说通过mongoose的model保存之后,最后会自动成为近乎以下那样的格式:

"gaming": [
      {
        "enter": 2017-04-25T14:32:12.081Z,
        "exit": 2017-04-25T14:48:52.082Z,
      },
      {
        "enter": 2017-04-26T14:32:12.081Z,
        "exit": 2017-04-26T14:48:52.082Z,
      },
      {
        "enter": 2017-04-27T14:22:12.021Z,
        "exit": 2017-04-27T15:32:12.031Z,
      },
      {
        "enter": 2017-04-26T16:22:12.082Z,
        "exit": 2017-04-26T16:52:12.082Z,
      }
    ],

那么那里要消除的题目正是:

  • 什么样将客户端传过来的新数组和从mongodb取回来的数组实行联合
  • 集合时怎么依照游戏进入的日子enter来去重复

理所当然,大家能够用原来的艺术,做两层遍历,分别便利三个例外的数组,然后将里面一个比对数据的类型转换来别的三个数目对应的门类,然后进行相比其是或不是等于,相等的话就去掉,不想等的话就将数据追加到数组中。

但,那样效能太低了,应该有更好的更优雅的艺术来帮衬我们处理那种题材。

前言

2. 尝试数据

那就是说大家就依照地方蒙受的标题,来树立三个实验所用的多少。多个是表示从mongodb取回来的多寡:

const orgGaming = [
      {
        "enter": new Date("2017-04-25T14:32:12.081Z"),
        "exit": new Date("2017-04-25T14:48:52.082Z"),
      },
      {
        "enter": new Date("2017-04-26T14:32:12.081Z"),
        "exit": new Date("2017-04-26T14:48:52.082Z"),
      }
]

三个是客户端传进来的数目:

const newGaming = [
     {
        "enter": 1493130732081, // 这和orgGamine第一条数据重复
        "exit": 1493131732082, // 这和orgGamine第一条数据重复
      },
      {
        "enter": 1493130735084,
        "exit": 1493131736087,
      }
    ]

新数组中的第二条数据和enter和数据库中的第③条数据的enter,事实上是平等的,所以我们期望统一之后那个重复数据是去掉的。

     
看完了Node.js实战,个中在数量存款和储蓄部分关联了Redis、Mongodb,作者本人也依据书中的介绍写了多少个大致的demo,在demo的历程首先碰着的标题就是数据类型和普遍的CU途睿欧D写法。
mongodb的常见操作有三种方式,一个是直接使用API,也就一定于您在SQL
Server客户端中央银行使T-SQL编写SQL语句来操作数据一致,其次就是在先后中接纳mongoose驱动来操作数据,也便是大家在先后里用ADO.NET或EF来操作数据,若是您早已写了多少个调用API的demo,那么小编提出再回过头来看看mongoose的API,多看API,并且记住常见的多少个格局比如where,skip,sort等

3. ES6数构成并新特性


实质上,假使不是因为要考虑去重新的题材来说,大家全然能够因而ES6的新特征来形成的。

array1.push(...array2)

此处的’…’操作符叫做扩张运算符,是ES6引入的新特点。目标是将二个数组打散成用逗号分隔的参数种类。

const array = [1, 2];
console.log(...array); // 相当于 console.log(1,2)

从而位置的言传身教代码的情致就是将array2打散后,将各类成分作为参数push到array第11中学变化新的数组。所以,即使接纳到我们的风貌中的话

const orgGaming = [
      {
        "enter": new Date("2017-04-25T14:32:12.081Z"),
        "exit": new Date("2017-04-25T14:48:52.082Z"),
      },
      {
        "enter": new Date("2017-04-26T14:32:12.081Z"),
        "exit": new Date("2017-04-26T14:48:52.082Z"),
      }
]

const newGaming = [
     {
        "enter": 1493130732081,
        "exit": 1493131732082,
      },
      {
        "enter": 1493130735084,
        "exit": 1493131736087,
      }
]

orgGaming.push(...newGaming);
console.log(orgGaming);

终极将会输出没有去重新的结果:

[ 
  { enter: 2017-04-25T14:32:12.081Z,
    exit: 2017-04-25T14:48:52.082Z },
  { enter: 2017-04-26T14:32:12.081Z,
    exit: 2017-04-26T14:48:52.082Z },
  { enter: 1493130732081, 
    exit: 1493131732082 },
  { enter: 1493130735084, 
    exit: 1493131736087 } 
]

当然,ES6的那些数组合并形式还足以如此写:

[...array1,...array2]

并且,ES6还提供了对简易数据类型去重新格局:

[...new Set([...array1 ,...array2])];

可是,那几个只好针对简单数据类型实行去重新,比如数字类型和字串类型等。

const array1 = ['techgogogo', 'sina', 'baidu'];
const array2 = ['techgogogo', 'google'];
console.log([... new Set([...array1, ...array2])]);

终极输出:

[ 'techgogogo', 'sina', 'baidu', 'google' ]

不过对于大家那里的目的类型组成的数组,它是做不到的。

最注重的是,它并未提供一个comparator的回调方法来放大家处理相应怎么着判定,多少个数据是或不是是重复的。

那边,lodash的数组操作,恐怕是个科学的化解方案(之一)。

    
按照现在大家编辑Web情势,大家会关切数据从客户端(Views)如若到Controller层,
然后把多少如何从Controller层传递到Dao层以及那八个层面传递数据时的一对技艺,那么在Node里那种考虑也是适用的。

4. lodash合并对象类型数组并去重新

lodash的unionWith格局得以统一多少个数组,并且能够让我们提供二个comparator方法来决定该怎么样相比八个数组中的成分是或不是是一致的,以此来判断这么些数据是不是是重复的。

法定文书档案对unionWith方法的描述请看那里:https://lodash.com/docs/4.17.4\#unionWith

_.unionWith([arrays], [comparator])

知晓起来也比较简单,请看代码如下:

const _ = require('lodash');
const orgGaming = [
      {
        "enter": new Date("2017-04-25T14:32:12.081Z"),
        "exit": new Date("2017-04-25T14:48:52.082Z"),
      },
      {
        "enter": new Date("2017-04-26T14:32:12.081Z"),
        "exit": new Date("2017-04-26T14:48:52.082Z"),
      }
]

const newGaming = [
     {
        "enter": 1493130732081,
        "exit": 1493131732082,
      },
      {
        "enter": 1493130735084,
        "exit": 1493131736087,
      }
]

gaming = _.unionWith(orgGaming, newGaming, (value1, value2) => {
    if (typeof value1.enter === 'number' && typeof value2.enter === 'number') {
        return (value1.enter === value2.enter);
    } else if (typeof value1.enter === 'number' && typeof value2.enter === 'object') {
        return (value1.enter === value2.enter.getTime());
    } else if (typeof value1.enter === 'object' && typeof value2.enter === 'number') {
        return (value1.enter.getTime() === value2.enter);
    } else if (typeof value1.enter === 'object' && typeof value2.enter === 'object') {
        return (value1.enter.getTime() === value2.enter.getTime());
    }
});

console.log(gaming);

此间根本的地方正是uionWith,有多少个地点必要小心:

  • 参数的顺序,尤其是前七个数组参数。纵然第②个数组中有些成员判定和第3个数组中的某些成员是再度的,那么首先个数组中的该因素会保留,第1个数组中的对应成分会移除。
  • 其三个参数正是二个回调方法,接受七个参数,其实便是多个须要比对的数组的积极分子,那里大家透过比对八个成员的enter是不是等于来判定该成员是不是再次。
  • 澳门永利备用网址,看清是不是再度的时候,大家须要将日志先转换到unixtime的格式,然后再开始展览相比。

末段大家能够阅览去重新后的输出:

[ { enter: 2017-04-25T14:32:12.081Z,
    exit: 2017-04-25T14:48:52.082Z },
  { enter: 2017-04-26T14:32:12.081Z,
    exit: 2017-04-26T14:48:52.082Z },
  { enter: 1493130735084, 
    exit: 1493131736087 } ]

能够看到,最终输出的列表中唯有多个对象,在那之中二个双重的早已被撤销掉了。

最终我们经过mongoose将那份数据存款和储蓄到mongodb时,如前方所述,会自动将unixtime转换来Date进行仓库储存,那样数据就集合起来了。那里mongoose的操作就不赘述了,有趣味的朋友能够团结履行下。

上述正是本人对五个由对象类型组成的数组举行合并的一部分尝试和进行,倘使我们有更好更优雅的方法的话,欢迎在评论中给出去。先拜谢了!

正文由世界会大庆分舵编写,转发需授权,喜欢点个赞,吐槽请评论,进一步调换请关心群众号techgogogo大概直接关联自个儿微信zhubaitian1

什么是MongoDB?

   MongoDB 是二个开源的 NoSQL 数据库,相比较 MySQL
那样的关系型数据库,它进一步轻巧、灵活,分外适合在数额规模非常大、事务性不强的场子下行使。 

Mongoose

Mongoose是包装了MongoDB的操作的3个对象模型库,为nodejs而生。就接近我们嫌原生javascript难写,代码量多,于是用jQuery库一样,因为MongoDB的操作接口复杂,不人性,所以有了Mongoose。那些库完全是可选的。
  
Mongoose的施用格外容易,在App的package.js中的dependence中加入mongoose,然后
npm install 即可。

 Mongodb数据类型

   1、null。{“x”:null}。

    2、Boolean。{“x”:true} 、{“x”:false}。

   叁 、数据类型。在Mongodb
Shell中暗中同意使用63人浮点型数据,如{“x”:2.32}、{“x”:2},若是要采用整数品种则用{“x”:NumberInt(2)}、{“x”:NumberLong(2)}。

    ④ 、字符串。Mongodb中字符串选拔UTF-8编码格局,{“x”:”hello world”}。

    ⑤ 、日期类型。{“x”:new Date()}。

    陆 、正则表明式。 Mongodb中可应用和javascript相同的正则表达式
{“x”:/itbilu/i}。

   
柒 、数据。Mongodb中数组的应用和javascript相同{“x”:[“hello”,”world”]}。

    捌 、内嵌文书档案。{“x”:{“y”:”Hello”}}。

   
⑨ 、Id和ObjectId()。Mongodb各种文书档案都会包含二个_id,假使您不点名时Mongodb会自动生成四个ObjectId对象。

    10、代码。{“x”:function aa(){}}。

    11、二进制。

常见CURD

var mongoose=require('mongoose');
var Schema=mongoose.Schema;
//1、连接字符串
mongoose.connect('mongodb://localhost/test');
//2、定义你的数据模型(也就是我们在关系数据库中定义的Table)
var TodoSchema=new Schema({
  title:String,
  finished:{type:Boolean,default:false},
  post_date:{type:Date,default:Date.now}
});
//3、访问todo对象模型
mongoose.model('Todo',TodoSchema);
//添加
exports.add=function(title,callback){
  var newTodo=new Todo();
  newTodo.title=title;
  newTodo.save(function(err){
    if(err){
      console.log(err);
      callback(err);
    }else{
      callback(null);
    }
  });
}
//查找单独的数据
var findTodoById=exports.findTodoById=function(id,callback){
  Todo.findOne({_id:id},function(err,doc){
    //doc也就是根据id得到的记录值
    if(err){
      callback(err,null);
    }
    callback(null,doc);
  })
}
//删除
exports.delete=function(id,callback){
  exports.findTodoById(id,function(err,doc){
    if(err){
      callback(err);
    }else{
      doc.remove();
      callback(null);
    }
  })
}
//编辑标题
exports.editTitle=function(id,title,callback){
  exports.findTodoById(id,function(err,doc){
    if(err){
      callback(err);
    }else{
      doc.post_date=new Date();
      doc.title=title;
      doc.save(function(err){
        if(err){
          callback(err);
        }else{
          callback(null);
        }
      })
    }
  })
}
exports.allTodos=function(callback){
  Todo.find({},callback);
}
//分页查询
exports.TodoPageList=function(pageIndex,pageSize,callback){
  var m=Todo.find({}); //也有方法直接这样写: var m=this;
  var start=(pageIndex-1)*pageSize;
  m.skip(start);
  m.limit(pageSize);
  m.sort({'post_date','asc'}); //排序
  //根据关键字查询后分页
  //m.where('title','XXX');
  //执行分页查询
  m.exec(function(err,rs){
    //分页后的结果
    if(err){
      callback(err);
    }else{
      Todo.find(function(err,result){
        /*
          一般情况下的分页你需要同时返回数据库记录总数和分页后的数据,所以这里使用了Todo.find再查询一次
        */
        callback({rows:rs,total:result.length});
      });
    }
  })
}

以上内容是小编给大家介绍的Mongodb 数据类型及Mongoose常用CU奇骏D
,希望我们欢乐。

您大概感兴趣的稿子: