• NodeJS:树的反序列化


    !!不知问啥,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存储数组文章
  • 相关阅读:
    原创 C++应用程序在Windows下的编译、链接(四)动态链接
    IE浏览器 json异常
    Linux系统github使用
    Mysql in 排序
    转 php四种基础算法:冒泡,选择,插入和快速排序法
    转 mysql取今天,明天,工作日,周末,本周,下周,下月数据
    下载远程图片到本地
    转 PHP中SQL_CALC_FOUND_ROWS与FOUND_ROWS()和count()
    星级点评
    21个值得收藏的Javascript技巧
  • 原文地址:https://www.cnblogs.com/edwardstudy/p/4166116.html
Copyright © 2020-2023  润新知