node的实践(项目二)

Posted 飘然离去

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了node的实践(项目二)相关的知识,希望对你有一定的参考价值。

找以前看看简单的demo,看看node是怎么操作Mongo然后又是渲染前台的,与前面的项目一中的对比。

1.操作Mongo数据库的方法和方式。

var mongodb = require(./db),
    markdown = require(markdown).markdown;

function Post(name, head, title, tags, post) {
  this.name = name;
  this.head = head;
  this.title = title;
  this.tags = tags;
  this.post = post;
}

module.exports = Post;

//存储一篇文章及其相关信息
Post.prototype.save = function(callback) {
  var date = new Date();
  //存储各种时间格式,方便以后扩展
  var time = {
      date: date,
      year : date.getFullYear(),
      month : date.getFullYear() + "-" + (date.getMonth() + 1),
      day : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(),
      minute : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + 
      date.getHours() + ":" + (date.getMinutes() < 10 ? 0 + date.getMinutes() : date.getMinutes())
  }
  //要存入数据库的文档
  var post = {
      name: this.name,
      head: this.head,
      time: time,
      title:this.title,
      tags: this.tags,
      post: this.post,
      comments: [],
      reprint_info: {},
      pv: 0
  };
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //将文档插入 posts 集合
      collection.insert(post, {
        safe: true
      }, function (err) {
        mongodb.close();
        if (err) {
          return callback(err);//失败!返回 err
        }
        callback(null);//返回 err 为 null
      });
    });
  });
};

//一次获取十篇文章
Post.getTen = function(name, page, callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      var query = {};
      if (name) {
        query.name = name;
      }
      //使用 count 返回特定查询的文档数 total
      collection.count(query, function (err, total) {
        //根据 query 对象查询,并跳过前 (page-1)*10 个结果,返回之后的 10 个结果
        collection.find(query, {
          skip: (page - 1)*10,
          limit: 10
        }).sort({
          time: -1
        }).toArray(function (err, docs) {
          mongodb.close();
          if (err) {
            return callback(err);
          }
          //解析 markdown 为 html
          docs.forEach(function (doc) {
            doc.post = markdown.toHTML(doc.post);
          });  
          callback(null, docs, total);
        });
      });
    });
  });
};

//获取一篇文章
Post.getOne = function(name, day, title, callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //根据用户名、发表日期及文章名进行查询
      collection.findOne({
        "name": name,
        "time.day": day,
        "title": title
      }, function (err, doc) {
        if (err) {
          mongodb.close();
          return callback(err);
        }
        if (doc) {
          //每访问 1 次,pv 值增加 1
          collection.update({
            "name": name,
            "time.day": day,
            "title": title
          }, {
            $inc: {"pv": 1}
          }, function (err) {
            mongodb.close();
            if (err) {
              return callback(err);
            }
          });
          //解析 markdown 为 html
          doc.post = markdown.toHTML(doc.post);
          doc.comments.forEach(function (comment) {
            comment.content = markdown.toHTML(comment.content);
          });
          callback(null, doc);//返回查询的一篇文章
        }
      });
    });
  });
};

//返回原始发表的内容(markdown 格式)
Post.edit = function(name, day, title, callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //根据用户名、发表日期及文章名进行查询
      collection.findOne({
        "name": name,
        "time.day": day,
        "title": title
      }, function (err, doc) {
        mongodb.close();
        if (err) {
          return callback(err);
        }
        callback(null, doc);//返回查询的一篇文章(markdown 格式)
      });
    });
  });
};

//更新一篇文章及其相关信息
Post.update = function(name, day, title, post, callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //更新文章内容
      collection.update({
        "name": name,
        "time.day": day,
        "title": title
      }, {
        $set: {post: post}
      }, function (err) {
        mongodb.close();
        if (err) {
          return callback(err);
        }
        callback(null);
      });
    });
  });
};

//删除一篇文章
Post.remove = function(name, day, title, callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //查询要删除的文档
      collection.findOne({
        "name": name,
        "time.day": day,
        "title": title
      }, function (err, doc) {
        if (err) {
          mongodb.close();
          return callback(err);
        }
        //如果有 reprint_from,即该文章是转载来的,先保存下来 reprint_from
        var reprint_from = "";
        if (doc.reprint_info.reprint_from) {
          reprint_from = doc.reprint_info.reprint_from;
        }
        if (reprint_from != "") {
          //更新原文章所在文档的 reprint_to
          collection.update({
            "name": reprint_from.name,
            "time.day": reprint_from.day,
            "title": reprint_from.title
          }, {
            $pull: {
              "reprint_info.reprint_to": {
                "name": name,
                "day": day,
                "title": title
            }}
          }, function (err) {
            if (err) {
              mongodb.close();
              return callback(err);
            }
          });
        }

        //删除转载来的文章所在的文档
        collection.remove({
          "name": name,
          "time.day": day,
          "title": title
        }, {
          w: 1
        }, function (err) {
          mongodb.close();
          if (err) {
            return callback(err);
          }
          callback(null);
        });
      });
    });
  });
};

//返回所有文章存档信息
Post.getArchive = function(callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //返回只包含 name、time、title 属性的文档组成的存档数组
      collection.find({}, {
        "name": 1,
        "time": 1,
        "title": 1
      }).sort({
        time: -1
      }).toArray(function (err, docs) {
        mongodb.close();
        if (err) {
          return callback(err);
        }
        callback(null, docs);
      });
    });
  });
};

//返回所有标签
Post.getTags = function(callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    //读取 posts 集合
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //distinct 用来找出给定键的所有不同值
      collection.distinct("tags", function (err, docs) {
        mongodb.close();
        if (err) {
          return callback(err);
        }
        callback(null, docs);
      });
    });
  });
};

//返回含有特定标签的所有文章
Post.getTag = function(tag, callback) {
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //查询所有 tags 数组内包含 tag 的文档
      //并返回只含有 name、time、title 组成的数组
      collection.find({
        "tags": tag
      }, {
        "name": 1,
        "time": 1,
        "title": 1
      }).sort({
        time: -1
      }).toArray(function (err, docs) {
        mongodb.close();
        if (err) {
          return callback(err);
        }
        callback(null, docs);
      });
    });
  });
};

//返回通过标题关键字查询的所有文章信息
Post.search = function(keyword, callback) {
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      var pattern = new RegExp(keyword, "i");
      collection.find({
        "title": pattern
      }, {
        "name": 1,
        "time": 1,
        "title": 1
      }).sort({
        time: -1
      }).toArray(function (err, docs) {
        mongodb.close();
        if (err) {
         return callback(err);
        }
        callback(null, docs);
      });
    });
  });
};

//转载一篇文章
Post.reprint = function(reprint_from, reprint_to, callback) {
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    db.collection(posts, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //找到被转载的文章的原文档
      collection.findOne({
        "name": reprint_from.name,
        "time.day": reprint_from.day,
        "title": reprint_from.title
      }, function (err, doc) {
        if (err) {
          mongodb.close();
          return callback(err);
        }

        var date = new Date();
        var time = {
            date: date,
            year : date.getFullYear(),
            month : date.getFullYear() + "-" + (date.getMonth() + 1),
            day : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(),
            minute : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + 
            date.getHours() + ":" + (date.getMinutes() < 10 ? 0 + date.getMinutes() : date.getMinutes())
        }

        delete doc._id;//注意要删掉原来的 _id

        doc.name = reprint_to.name;
        doc.head = reprint_to.head;
        doc.time = time;
        doc.title = (doc.title.search(/[转载]/) > -1) ? doc.title : "[转载]" + doc.title;
        doc.comments = [];
        doc.reprint_info = {"reprint_from": reprint_from};
        doc.pv = 0;

        //更新被转载的原文档的 reprint_info 内的 reprint_to
        collection.update({
          "name": reprint_from.name,
          "time.day": reprint_from.day,
          "title": reprint_from.title
        }, {
          $push: {
            "reprint_info.reprint_to": {
              "name": doc.name,
              "day": time.day,
              "title": doc.title
          }}
        }, function (err) {
          if (err) {
            mongodb.close();
            return callback(err);
          }
        });

        //将转载生成的副本修改后存入数据库,并返回存储后的文档
        collection.insert(doc, {
          safe: true
        }, function (err, post) {
          mongodb.close();
          if (err) {
            return callback(err);
          }
          callback(err, post[0]);
        });
      });
    });
  });
};

2.操作mysql的方式;

use strict;

var pool = require(./pool);
var Util = require(../utils/util);

function User(data) {
  this.userId            = data.userId;         //用户id
  this.userLogin         = data.userLogin;      //用户名
  this.userPass          = data.userPass;       //密码
  this.userSalt          = data.userSalt;       //加密时使用的盐
  this.userNicename      = data.userNicename;   //名字,通常为中文名
  this.userEmail         = data.userEmail;      //邮箱
  this.userRegistered    = data.userRegistered || new Date(); //注册日期
  this.userStatus        = data.userStatus;     //用户状态
  this.privilege         = data.privilege;      //权限
}

User.ITERATIONS = 8;

User.KEY_LEN    = 64;

User.PWD_LENGTH = 128;

/**
 * 根据id来查找用户
 * @static method findById
 * @for User
 * @param {Number} id 用户id
 * @param {Function} callback 回调函数,第一个参数是错误对象或null,第二个参数是User对象
 */
User.findById = function(id, callback) {
  if (!Util.isInt(id)) {
    return callback(new Error(id is not an integer));
  }
  pool.getConnection(function(err, conn) {
    if (err) {
      return callback(err);
    }
    var sql = SELECT * FROM cp_user WHERE user_id = ?;
    conn.query(sql, [id], function(err, rows, fields) {
      conn.release();
      var user;
      if (!err && rows.length) {
        var userData            = {};
        userData.userId         = rows[0].user_id;
        userData.userLogin      = rows[0].user_login;
        userData.userPass       = rows[0].user_pass;
        userData.userSalt       = rows[0].user_salt;
        userData.userNicename   = rows[0].user_nicename;
        userData.userEmail      = rows[0].user_email;
        userData.userRegistered = rows[0].user_registered;
        userData.userStatus     = rows[0].user_status;
        user                    = new User(userData);
      }
      callback(err, user);
    });
  });
};

/**
 * 根据email来查找用户
 * @static method findByEmail
 * @for User
 * @param {String} email 邮箱
 * @param {Function} callback 回调函数,第一个参数是错误对象或null,第二个参数是User对象
 */
User.findByEmail = function(email, callback) {
  if (!Util.isString(email)) {
    return callback(new Error(email is not a string type));
  }
  pool.getConnection(function(err, conn) {
    if (err) {
      callback(err);
    } else {
      var sql = SELECT * FROM cp_user WHERE user_email = ?;
      conn.query(sql, [email], function(err, rows, fields) {
        conn.release();
        var user;
        if (!err && rows.length) {
          var userData            = {};
          userData.userId         = rows[0].user_id;
          userData.userLogin      = rows[0].user_login;
          userData.userPass       = rows[0].user_pass;
          userData.userSalt       = rows[0].user_salt;
          userData.userNicename   = rows[0].user_nicename;
          userData.userEmail      = rows[0].user_email;
          userData.userRegistered = rows[0].user_registered;
          userData.userStatus     = rows[0].user_status;
          user                    = new User(userData);
        }
        callback(err, user);
      });
    }
  });
};

/**
 * 查找指定数目的用户,若没有start,count这两个参数,表示要查找所有的用户
 * @static method findUsers
 * @for User
 * @param {Number} start 索引,索引从0开始
 * @param {Number} count 要查找的用户数目
 * @param {Function} callback 回调函数,第一个参数是错误对象或null,第二个参数是User对象数组
 */
User.findUsers = function(start, count, callback) {
  if (!Util.isInt(start)) {
    return callback(new Error(start is supposed to be an integer));
  }
  if (!Util.isInt(count)) {
    return callback(new Error(count is supposed to be an integer));
  }
  if (count <= 0) {
    return callback(new Error(count must be greater than 0));
  }
  pool.getConnection(function(err, conn) {
    if (err) {
      callback(err);
    } else {
      var sql = SELECT * FROM cp_user LIMIT ?, ?;
      var arr = [start, count];
      conn.query(sql, arr, function(err, rows, fields) {
        conn.release();
        if (err) {
          rows = [];
        }
        for (var i = 0; i < rows.length; i++) {
          var userData            = {};
          userData.userId         = rows[i].user_id;
          userData.userLogin      = rows[i].user_login;
          userData.userPass       = rows[i].user_pass;
          userData.userSalt       = rows[i].user_salt;
          userData.userNicename   = rows[i].user_nicename;
          userData.userEmail      = rows[i].user_email;
          userData.userRegistered = rows[i].user_registered;
          userData.userStatus     = rows[i].user_status;
          rows[i]                 = new User(userData);
        }
        callback(err, rows);
      });
    }  
  });
};

/**
 * 查找所有的用户
 * @static method findAll
 * @for User
 * @param {Function} callback 回调函数,第一个参数是错误对象或null,第二个参数是User对象数组
 */
User.findAll = function(callback) {
  pool.getConnection(function(err, conn) {
    if (err) {
      callback(err);
    } else {
      var sql = SELECT * FROM cp_user;
      conn.query(sql, function(err, rows, fields) {
        conn.release();
        if (err) {
          rows = [];
        }
        for (var i = 0; i < rows.length; i++) {
          var userData            = {};
          userData.userId         = rows[i].user_id;
          userData.userLogin      = rows[i].user_login;
          userData.userPass       = rows[i].user_pass;
          userData.userSalt       = rows[i].user_salt;
          userData.userNicename   = rows[i].user_nicename;
          userData.userEmail      = rows[i].user_email;
          userData.userRegistered = rows[i].user_registered;
          userData.userStatus     = rows[i].user_status;
          rows[i]                 = new User(userData);
        }
        callback(err, rows);
      });
    }  
  });
};

/**
 * 根据email来修改用户的密码
 * @static method updatePwdByEmail
 * @for User
 * @param {String} email 邮箱
 * @param {String} passwd 密码
 * @param {Function} callback 回调函数,参数是错误对象或null
 */
User.updatePwdByEmail = function(email, passwd, callback) {
  if (!Util.isString(email)) {
    return callback(new Error(email is not a string type));
  }
  if (!Util.isString(passwd)) {
    return callback(new Error(passwd is not a string type));
  }
  if (passwd.length !== User.PWD_LENGTH) {
    return callback(new Error(passwd.length != User.PWD_LENGTH));
  }
  pool.getConnection(function(err, conn) {
    if (err) {
      callback(err);
    } else {
      var sql = UPDATE cp_user SET user_pass = ? WHERE user_email = ?;
      conn.query(sql, [passwd, email], function(err) {
        conn.release();
        callback(err);
      });
    }
  });
};

/**
 * 根据id来修改用户的密码
 * @static method updatePwdById
 * @for User
 * @param {Number} id 用户id
 * @param {String} passwd 密码
 * @param {Function} callback 回调函数,参数是错误对象或null
 */
User.updatePwdById = function(id, passwd, callback) {
  if (!Util.isInt(id)) {
    return callback(new Error(id is not an integer));
  }
  if (!Util.isString(passwd)) {
    return callback(new Error(passwd is not a string type));
  }
  if (passwd.length !== User.PWD_LENGTH) {
    return callback(new Error(passwd.length != User.PWD_LENGTH));
  }
  pool.getConnection(function(err, conn) {
    if(err) {
      callback(err);
    }else {
      var sql = UPDATE cp_user SET user_pass = ? WHERE user_id = ?;
      conn.query(sql, [passwd, id], function(err, result) {
        conn.release();
        callback(err);
      });
    }
  });
};

/**
 * 新增一个用户
 * @method save
 * @for User
 * @param {Function} callback 回调函数,第一个参数是错误对象或null,第二个参数是User对象
 */
User.prototype.save = function(callback) {
  var self = this;
  pool.getConnection(function(err, conn) {
    if(err) {
      return callback(err);
    }
    var sql = INSERT INTO cp_user (user_login, user_salt, user_pass, user_nicename, user_email, user_registered, user_status) VALUES (?,?,?,?,?,?,?);
    var arr = [ self.userLogin, self.userSalt, self.userPass, self.userNicename, 
                self.userEmail, self.userRegistered, self.userStatus];
    conn.query(sql, arr, function(err, result) {
      conn.release();
      if(!err) {
        self.userId = result.insertId; 
      }
      callback(err, self);
    });
  });
};

/**
 * 有些属性不能暴露给客户端,返回一个只有部分属性的User对象
 * @method toUser
 * @for User
 * @return {User} 返回一个User对象
 */
User.prototype.toUser = function() {
  var user = new User(this);
  delete user.userPass;
  delete user.userSalt;
  return user;
};

 

以上是关于node的实践(项目二)的主要内容,如果未能解决你的问题,请参考以下文章

《Node.js在CLI下的工程化体系实践》成都OSC源创汇分享总结

Node.js JavaScript 片段中的跳过代码

52合1Node.js 最佳实践大合集

使用Node.js完成的第一个项目的实践总结

Apollo Codegen 没有找到生成代码的操作或片段

node的实践(项目三)