!!不知问啥,cnblog的MarkDown编辑器不好使了。

本文也在我的博客edwardesire.com上,欢迎品尝。


树的反序列化就是将序列数组安装线索组成树结构,今次项目数据库存储决策节点的方式是通过数组进行,每个节点有一个parent_id键直指双亲节点的node_id键,而在前端展示是决策树的结构。这是在比较在MongoDB存储数组的性能和前后台实现难度下决定的(在此呜谢师哥)。


  1. 数据库中的文档

    先来看看存储在数据库中的数据,后台通过ObjectId找到样例文档。注意这里,如果直接使用.findById(checkId,callback),回调函数得到结果为MongooseDocuments(其子文档都是embedded document类型,这一类型又有许多多余的参数),这个东西不太适合操作。应该需要使用Mongoose的API lean(),此方法得到的是一个javascript objects。

    javascript的objects相对就容易操作了,亲身经历。

     Dtree.findById(checkId).lean().exec( function(err, dtrees){
    node_array = dtrees.node_array;
    console.log(dtrees);
    console.log('node_array: ',node_array);
    //nodes node_array 树结构
    nodes = arrayToTree(node_array);
    //排序
    nodes = sortNodes(nodes);
    console.log('nodes: ', JSON.stringify(nodes));
    }

    这里得到的dtrees就是一个纯粹javascript object。

  2. arrayToTree方法

    在上节可以看到,我截取了dtrees的node_array作为参数调用方法arrayToTree,参照的是ling凌yue月的文章。首先将数组按升序排序,以便接下来的操作。从数组尾开始,找到它的双亲节点,插入双亲节点的children数组中。最后得到的根节点(node_id===1)就是一颗完整的树。

       /**
    * 将dtree的节点反序列化为树结构
    * @function arrayToTree
    * @param {Array} node_array dtree文档中的node_array节点数组
    * @return {Object Node} temp_array[0] 包含树结构的根节点
    */
    var arrayToTree = function(node_array){
    var temp_array = node_array;
    //将节点数组升序
    temp_array.sort(function(a, b){
    return a.node_id-b.node_id
    });
    //节点的children定义为空数组,@TODO 是否可以删除
    node_array.forEach(function(node){
    node.children = []; //children is Array
    });
    //从下往上将每个节点添加到父节点的children数组中
    var i = 0;
    var count = temp_array.length;
    for(i = (count - 1); i > 0; i-- ){
    if(temp_array[temp_array[i].parent_id - 1] !== null){
    var tNode = temp_array[i];
    temp_array[tNode.parent_id - 1].children.push(tNode);
    }
    }
    return temp_array[0];
    }
  3. sortNodes方法

    我们得到的树在结构上还有问题,其每层的节点序号大小事逆序的,也就是说节点1的子节点数组是[node[3], node[4]]。这个细节在传到前台可能会导致展示问题(与需要展示的内容互为镜像)。

     /**
    * 将树的每层子节点排序,递归
    * @function sortNodes
    * @param {Object Node} nodes 包含树结构的根节点,子节点的顺序为降序
    * @return {Object Node} nodes 原物奉还,各子节点数组的顺序为升序
    */
    var sortNodes = function(nodes){
    if(nodes.children.length > 0){
    var i = 0;
    for(; i < nodes.children.length; i++){
    nodes.children[i] = sortNodes(nodes.children[i]);
    }
    nodes.children.sort(function(a, b){
    return a.node_id-b.node_id
    });
    }
    return nodes;
    }
  4. 总结

    这周工作量看起来很轻松,实际完成起来还是花了不少时间。当然还有一些其他课程的作业也占用了不少时间。树的反序列化可能还有需要改进的地方。洛阳亲友如相问,午夜清风四零零。


Notes:

  1. Thinking about arrays in mongodb—monglab上一篇关于在MongoDB存储数组文章

NodeJS:树的反序列化的更多相关文章

  1. NodeJS:树的序列化

    本文也在我的博客edwardesire.com上,欢迎品尝. 接着上周的工作,我们把上周反序列得到的dtree对象输出到JSON,再将其序列化后存入MongoDB. 存入文档 先将上次得到的决策树对象 ...

  2. nodejs - json序列化&反序列化示例

    // demo-json.js var obj = { "name": "LiLi", "age": 22, "sex" ...

  3. [LintCode] Serialize and Deserialize Binary Tree(二叉树的序列化和反序列化)

    描述 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”. 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉 ...

  4. Node.js快速入门

    Node.js是什么? Node.js是建立在谷歌Chrome的JavaScript引擎(V8引擎)的Web应用程序框架. 它的最新版本是:v0.12.7(在编写本教程时的版本).Node.js在官方 ...

  5. 学习node.js 第2篇 介绍node.js 安装

    Node.js - 环境安装配置 如果愿意安装设置Node.js环境,需要计算机上提供以下两个软件: 一.文本编辑器 二.Node.js二进制安装包 文本编辑器 这将用来编写程序代码. 一些编辑器包括 ...

  6. Zookeeper原理分析之存储结构ZkDatabase

    ZKDatabase在内存中维护了zookeeper的sessions, datatree和commit logs集合. 当zookeeper server启动的时候会将txnlogs和snapsho ...

  7. BFS (1)算法模板 看是否需要分层 (2)拓扑排序——检测编译时的循环依赖 制定有依赖关系的任务的执行顺序 djkstra无非是将bfs模板中的deque修改为heapq

    BFS模板,记住这5个: (1)针对树的BFS 1.1 无需分层遍历 from collections import deque def levelOrderTree(root): if not ro ...

  8. NodeJS反序列化漏洞利用

    原文来自:http://www.4hou.com/web/13024.html node.js是一个服务器端的运行环境,封装了Google V8引擎,V8引擎执行JavaScript速度非常快,性能非 ...

  9. 02.树的序列化与反序列化(C++)

    1.二叉树的序列化 输入的一棵树: //二叉树的先序遍历-序列化 #include <iostream> #include <string> #include <sstr ...

随机推荐

  1. Android设置TextView显示一行或多行

    在listView的item中或者是特殊的业务需求中,会要求TextView的内容不完全显示,只有通过一个指定的操作后才显示所有的,比如说一个按钮或者是其它的什么控件. 要想实现这个效果并不难,只要控 ...

  2. xargs的- n1参数

    起因在对一堆*.tar.gz文件解压缩时,发现tar xvfz *.tar.gz不管用,一查,原来是tar xvfz *.tar.gz会被shell给拆成tar xvfz a.tar.gz b.tar ...

  3. [POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)

    题目链接:http://poj.org/problem?id=1330 题意就是求一组最近公共祖先,昨晚学了离线tarjan,今天来实现一下. 个人感觉tarjan算法是利用了dfs序和节点深度的关系 ...

  4. Android wakelock机制

      Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠,可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的,超时的锁会在时间过去以后自动解锁. 如果没有锁了或者 ...

  5. drop.delete.trauncat的区别

    delete删除数据,保留表结构,可以回滚,如果数据量大,很慢,回滚是因为备份了删除的数据(删除数据时有两个动作,删除和备份) truncate删除所有数据,保留表结构,不可以回滚,一次全部删除所有数 ...

  6. 基于XMPP的即时通信系统的建立(六)— 开发环境搭建

    服务器端 新建空工程 使用Eclipse新建名为openfire的空java工程. 导入源代码 这里使用的是openfire的openfire_src_3_10_3.zip源码. 导入后将目录src/ ...

  7. JS省队集训记

    不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...

  8. CentOS6.2下fastDFS的完整安装和配置步骤

    centos6.2系统下安装配置FastDFS步骤: 1:安装libevent(libevent-2.0.16-stable) ##卸载系统自带libevent rpm -qa|grep libeve ...

  9. [反汇编练习] 160个CrackMe之015

    [反汇编练习] 160个CrackMe之015. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

  10. Darwin Streaming Server 安裝操作備忘

    Darwin Streaming Server 安裝操作 Darwin Streaming Server是蘋果公司推出的開放源碼.跨平台多媒體串流伺服器, 提供音樂 (mp3) 與影音 (3gp.mp ...