`
izuoyan
  • 浏览: 9295565 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

MongoDB学习之树结构例子(使用NORM驱动)

阅读更多

近期NoSql数据库比较火,于是本着与时俱进的态度,开始对MongoDB进行学习。学习的最好方法就是动手做做实例,于是选择了经常使用到的树结构作为入门例子。本例子将根据《Tree in MongoDB》推荐的全路径方法构建树结构。

首先要做的是如图一所示的操作页面。

mongo-tree

图一 操作页面

操作页面很简单,就是用Ext的树控件创建一个树结构,通过控件上的小按钮对树进行添加、删除操作。直接单击树节点可的节点文字进行修改。因为本文的重点不是Ext界面,所以操作页面的代码就不多说,有兴趣可以下载源代码进行研究。

下面主要来学习一下操作MongoDB后台代码。首先是要根据树结构定义一个类,类定义如下:

public class Node
{
    public ObjectId ID { get; set; }
    public string title {get;set;}
    public int depth { get; set; }
    public string path { get; set; }
}


从类定义中可以看到,树节点的存储结构主要有4个项,ID为唯一编号,title为节点名称,depth是节点的深度, path是节点的全路径。

下面要完成的是子节点的查询操作,代码如下:

    private string List(HttpContext context)
    {
        string nodeid = context.Request.Params["node"] ?? "";
        JArray ja = new JArray();
        using (var mongo = Mongo.Create("mongodb://192.168.0.77/Trees"))
        {
            var nodes = mongo.GetCollection<Node>("Node");
            if (nodeid == "" | nodeid == "rootnode")
            {
                var q = nodes.Find(new { depth = 0 });
                foreach (var c in q)
                {
                    ja.Add(new JObject(
                        new JProperty("id", c.ID.ToString()),
                        new JProperty("text", c.title),
                        new JProperty("leaf", false)
                        ));
                }
            }
            else
            {
                Node node = nodes.FindOne(new { _id = new ObjectId(nodeid) });
                if (node != null)
                {
                    var q = nodes.Find(new { path = new Regex("^" + node.path), depth = node.depth + 1 });
                    foreach (var c in q)
                    {
                        ja.Add(new JObject(
                            new JProperty("id", c.ID.ToString()),
                            new JProperty("text", c.title),
                            new JProperty("leaf", false)
                            ));
                    }
                }
            }
        }
        return ja.ToString();
    }


List方法的代码中,第一行是获取父节点id。JArry对象ja的作用是返回子节点数组。要注意以下这句:

using (var mongo = Mongo.Create("mongodb://192.168.0.77/Trees"))

这里建议使用using关键字,主要原因是让对象自动释放连接,不然当操作频繁的时候,因为连接没有释放,会产生“norm.mongo exception: connection timeout trying to get connection from connection pool”的错误。在调试时,很是困扰了笔者一段时间。

在有些文章会使用new MongoDB连接数据库,具体有什么不同,笔者没仔细研究。使用Create方法是根据NORM的测试例子依样画葫芦而已。这个可根据个人习惯选择。如果MongoDB的端口不同,可在IP地址后加上端口号,譬如端口号为10000,可修改代码如下:

using (var mongo = Mongo.Create("mongodb://192.168.0.77:10000/Trees"))


连接字符串中的“Trees”为要连接的数据库名称。

下面一句就是从数据库中获取数据集合。如果需要返回根节点的子节点,则直接搜索depth为0的节点就行。否则需要先通过FindOne方法获取父节点,然后使用父节点的路径(path)通过正则表达式查询其子节点。在这里因为要返回的只是父节点的下一级子节点,所以需要增加一个节点深度条件(depth = node.depth + 1)。

下面是Add方法的代码,用来增加树节点:

    private string Add(HttpContext context)
    {
        string output = "";
        string title = context.Request.Params["value"] ?? "";
        if (title.Length > 0)
        {
            string nodeid = context.Request.Params["parentid"] ?? "";
            using (var mongo = Mongo.Create("mongodb://192.168.0.77/Trees"))
            {
                var nodes = mongo.GetCollection<Node>("Node");
                var node = new Node();
                node.ID = ObjectId.NewObjectId();
                node.title = title;
                node.depth = 0;
                node.path = node.ID + ",";
                if (nodeid.Length > 0)
                {
                    Node q = nodes.FindOne(new { _id = new ObjectId(nodeid) });
                    if (q != null)
                    {
                        node.depth = q.depth + 1;
                        node.path = q.path + node.ID + ",";
                    }
                }
                nodes.Insert(node);
                output = (new JObject
                    {
                        new JProperty("success",true),
                        new JProperty("data",new JObject(
                                new JProperty("id",node.ID.ToString()),
                                new JProperty("text",node.title),
                                new JProperty("leaf",false)
                            ))
                    }).ToString();
            }
        }
        else
        {
            output = (new JObject
            {
                new JProperty("success",false),
                new JProperty("data","请输入节点名称")
            }).ToString();
        }         
        return output;
    }


添加子节点比较简单,只要创建一个Node对象,然后使用Inser方法保存就行了。新创建的Node对象默认是顶层节点,如果父节点存在,则修改Node对象的depth属性和path属性即可。

下面是Del方法的代码,用于删除节点:

    private string Del(HttpContext context)
    {
        string output="";
        string id = context.Request.Params["id"] ?? "";
        if (id.Length > 0)
        {
            using (var mongo = Mongo.Create("mongodb://192.168.0.77/Trees"))
            {
                var nodes = mongo.GetCollection<Node>("Node");
                Node q = nodes.FindOne(new { _id = new ObjectId(id) });
                if (q != null)
                {
                    nodes.Delete(new { path = new Regex("^" + q.path) });
                    output = (new JObject
                        {
                            new JProperty("success",true),
                            new JProperty("data",id)
                        }).ToString();
                }
                else
                {
                    output = (new JObject
                        {
                            new JProperty("success",false),
                            new JProperty("data","要删除的节点不存在或已被删除!")
                        }).ToString();
                }
            }
        }
        else
        {
            output = (new JObject
            {
                new JProperty("success",false),
                new JProperty("data","请选择要删除的节点!")
            }).ToString();
        }
        return output;
    }


因为使用全路径的结构,所以删除一个节点及其子节点变得相当简单,只要通过该节点的全路径,使用正则表达式搜索到节点本身及其子节点就行了。在例子中使用以下语句就轻松完成了删除操作:

nodes.Delete(new { path = new Regex("^" + q.path) });


下面是Edit方法的代码,用于修改节点的名称:

    private string Edit(HttpContext context)
    {
        string output = "";
        string id = context.Request.Params["id"] ?? "";
        string title = context.Request.Params["value"] ?? "";
        if (title.Length > 0)
        {
            if (id.Length > 0)
            {
                using (var mongo = Mongo.Create("mongodb://192.168.0.77/Trees"))
                {
                    var nodes = mongo.GetCollection<Node>("Node");
                    Node q = nodes.FindOne(new { _id = new ObjectId(id) });
                    if (q != null)
                    {
                        q.title = title;
                        nodes.Save(q);
                        output = (new JObject
                        {
                            new JProperty("success",true),
                            new JProperty("data",id)
                        }).ToString();
                    }
                    else
                    {
                        output = (new JObject
                            {
                                new JProperty("success",false),
                                new JProperty("data","要修改的节点不存在或已被删除!")
                            }).ToString();
                    }
                }
            }
            else
            {
                output = (new JObject
                {
                    new JProperty("success",false),
                    new JProperty("data","要修改的节点不存在或已被删除!")
                }).ToString();
            }
        }
        else
        {
            output = (new JObject
                {
                    new JProperty("success",false),
                    new JProperty("data","请输入节点名称!")
                }).ToString();
        }
        return output;        
    }


代码中首先要判断提交过来的节点名称是否为空,如果不为空则继续判断提交的节点id是否正确,接着需要通过 FindOne方法搜索节点,修改title属性后,通过save方法保存即可完成操作。

例子已经完成了,从例子中可以看到,使用NORM操作MongoDB相当方便,代码很简洁。

通过例子可以看到,使用全路径的方法,在MongoDB中创建一个无级树是相当的方便,因为路径不受数据库字段长度的限制,不过如果考虑MongoDB的存储大小的话,估计也是一个问题,不过这个有待测试。这也是NoSql数据库的一个优势吧。


源代码下载地址:http://download.csdn.net/source/2652662

分享到:
评论

相关推荐

    mongodb-tree-structure:在MongoDB中实现树结构

    一种使用一个MongoDB集合实现树结构的方法。 显示模式设计和CRUD概念的一些基本思想。 在示例代码中使用和 。 [警告] 根据我很少的经验,这只是一种实现树结构的方法。 这可能不是您情况下的最佳选择。 如果您有...

    DBeaver新增MongoDB驱动

    MongoDB驱动

    MongoDB之Java使用例子

    在这个“MongoDB之Java使用例子”中,我们将深入探讨如何在Java环境中操作MongoDB数据库,包括增、删、改、查(CRUD)操作以及图像数据的存储和检索。 首先,Java与MongoDB的交互主要通过MongoDB的Java驱动程序实现...

    MongoDB中C#驱动的Norm.dll下载

    在使用Norm.dll之前,首先需要确保你的项目中已经安装了MongoDB的官方C#驱动程序,这个驱动通常通过NuGet包管理器安装,名为"MongoDB.Driver"。 Norm.dll提供了以下主要功能: 1. **连接管理**:Norm.dll允许...

    MongoDB学习文档.zip

    总的来说,"MongoDB学习文档.docx"可能涵盖了MongoDB的基本概念、Java驱动的使用、数据操作、复制集和分片等核心内容,是初学者和进阶者学习MongoDB与Java结合使用的宝贵资源。通过深入学习这份文档,开发者可以掌握...

    MongoDBjava各版本驱动下载

    MongoDB提供了多种语言的驱动程序,Java驱动是其中之一。它基于Java 6及更高版本,实现了MongoDB的Wire Protocol,允许Java应用与MongoDB进行通信。Java驱动分为几个主要版本,每个版本可能对应不同的功能特性和兼容...

    MongoDB 学习资料集锦

    不同于传统的关系型数据库,MongoDB使用JSON格式的文档存储数据,这使得数据结构更加灵活,适合处理结构不固定或变化频繁的数据。同时,MongoDB支持多种数据类型,包括字符串、数字、日期、数组等,这为处理复杂的...

    mongodb例子

    MongoDB是一个基于分布式文件存储的开源数据库系统,广泛应用于现代应用程序开发中,特别是在处理大量非结构化或半结构化数据时。在这个“mongodb例子”中,我们很可能会找到一个简单的MongoDB数据库操作示例,这...

    mongodb必用驱动包

    mongodb必用驱动包架包jar包

    使用mongodb数据库做的小例子

    公司里要用mongodb数据库存放文件,给我一个星期的时间让我研究,这是我用mongodb数据库+struts写的小例子,能够实现人员的注册,头像的上传,帖子的管理。功能简单,主要让大家看看mongodb数据库的具体使用。文档写...

    mongodb c#驱动最新驱动mongodb.driver.dll 版本2.12.0-beta1

    C# 驱动是 MongoDB 提供的一种客户端库,允许 .NET 开发者与 MongoDB 数据库进行交互。标题提到的是 MongoDB 的 C# 驱动的最新版本——mongodb.driver.dll,具体为 2.12.0-beta1 版本。 MongoDB.Driver.dll 是 C# ...

    MongoDB的JDBC驱动

    MongoDB驱动jar包(MongoDB的Java连接包),3.7.0版本,适配MongDB 3.7.0及以下所有版本的MongoDB

    spring mongodb很好的例子

    在IT领域,Spring框架是Java开发中的一...通过分析和学习`HelloSpringWithMongoDB-master`这个示例项目,开发者可以更好地理解如何在实际应用中结合Spring MVC和Spring Data MongoDB,实现与MongoDB数据库的高效交互。

    mongodb学习笔记资料

    mongodb学习笔记资料,从安装到操作库collection 对document的crud 索引 replicaSet sharding 备份与恢复

    mongodb的java驱动包

    这是一个java的mongodb的驱动包,使用它就能够与用java去连接mongodb服务器,和操作mongodb

    MongoDB C/C++开发使用案例Demo

    MongoDB是一种流行的开源...实践中,你可以根据提供的源代码例子进行学习,理解每一步的操作,并尝试自定义功能,进一步熟悉MongoDB的C++ API。在实际项目开发中,这些知识将有助于你构建高效稳定的数据存储解决方案。

    Mongodb 学习 PPT上课教程

    MongoDB 学习 PPT 上课教程 MongoDB 是一个开源的、基于分布式的、面向文档存储的非关系型数据库。 MongoDB 的出现是为了解决大规模数据集合、多种数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的...

    mongodb驱动C#版1.7

    在 .NET 开发环境中,C# 是一种常用的编程语言,为了与 MongoDB 进行交互,需要使用专门的 MongoDB .NET 驱动。本压缩包提供的是 MongoDB 的 C# 版驱动程序,版本为 1.7。 MongoDB.C# 驱动是官方支持的 .NET 库,它...

    mongodb的java驱动jar包3.7.0

    MongoDB的Java驱动是连接Java应用程序与MongoDB数据库的关键组件,3.7.0版本是这一驱动的一个稳定发行版。这个压缩包包含了三个核心的JAR文件,它们分别是`mongodb-driver-3.7.0.jar`、`mongodb-driver-core-3.7.0....

    mongodb学习手册

    1. **文档型数据库**:MongoDB 使用 BSON(Binary JSON)格式存储数据,这是一种轻量级的二进制数据格式,支持嵌套结构,使得复杂数据结构的存储变得简单。 2. **集合与文档**:数据以集合的形式存在,集合类似于...

Global site tag (gtag.js) - Google Analytics