MongoDB的集合(collection)可以看做关系型数据库的表,文档对象(document)可以看做关系型数据库的一条记录。但两者并不完全对等。表的结构是固定的,MongoDB集合并没有这个约束;另外,存入集合的文档对象甚至可以嵌入子文档,或者“子集合”。他们最终都可以用类似于BJSON的格式描述。我们今天就来分析MongoDB这一特性带来的独特数据管理方式。我们还是以samus驱动为例来分析,samus驱动支持两种方式访问数据库,基本方式和linq方式,基本方式在上篇以介绍过,linq方式我不想单独讲解应用实例,这篇我会用两种方式来对比介绍。

一、包含子文档的集合操作

  有这么一个应用场景,某网站提供会员登录的功能,用户需要注册账号才能享受会员服务,但是注册者可能会因为用户资料表单输入项过大而放弃填写,因此用户信息分为主要资料和详细资料两项,初次注册只需要填写主要资料就行了。我们打算把详细信息设计为子文档存储。

   1) linq方式实现

  1. 新建数据描述类,描述用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// <summary>
/// 用户主要资料
/// </summary>
public class UserInfo
{
    public string UserId { get; set; }
    public string UserName { get; set; }
    public string PassWord { get; set; }
    public Detail Detail { get; set; }
}
 
/// <summary>
/// 用户详细资料
/// </summary>
public class Detail
{
    public string Address { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

  2. 我们要新建一个用户业务操作类“UserBLL”。这个时候要让驱动知道UserInfo类描述了“用户资料”的字段信息,在GetMongo()方法实现了配置步骤,UserBLL完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class UserBLL
{
    public string connectionString = "mongodb://localhost";
    public string databaseName = "myDatabase";
 
    private Mongo mongo;
    private MongoDatabase mongoDatabase;
 
    //注意这里泛型类型为“UserInfo”
    private MongoCollection<UserInfo> mongoCollection;
 
    public UserBLL()
    {
        mongo = GetMongo();
        mongoDatabase = mongo.GetDatabase(databaseName) as MongoDatabase;
        mongoCollection = mongoDatabase.GetCollection<UserInfo>() as MongoCollection<UserInfo>;
        mongo.Connect();
    }
    ~UserBLL()
    {
        mongo.Disconnect();
    }
 
    /// <summary>
    /// 配置Mongo,将类UserInfo映射到集合
    /// </summary>
    private Mongo GetMongo()
    {
        var config = new MongoConfigurationBuilder();
        config.Mapping(mapping =>
        {
            mapping.DefaultProfile(profile =>
            {
                profile.SubClassesAre(t => t.IsSubclassOf(typeof(UserInfo)));
            });
            mapping.Map<UserInfo>();
        });
        config.ConnectionString(connectionString);
        return new Mongo(config.BuildConfiguration());
    }
}

  3. 接着,在“UserBLL”类中定义一个方法“InsertSomeData()”来插入一些数据:

  4. 定义一个查找数据的方法“Select”,它将查找用户详细信息中,地址在湖北的全部用户:

1
2
3
4
5
6
7
/// <summary>
/// 查询详细资料地址为湖北的用户信息
/// </summary>
public List<UserInfo> Select()
{
    return mongoCollection.Linq().Where(x => x.Detail.Address == "湖北").ToList();
}

  5. 还定义一个删除数据的方法,将删除集合全部数据:

1
2
3
4
5
6
7
/// <summary>
/// 删除全部用户信息
/// </summary>
public void DeleteAll()
{
    mongoCollection.Remove(x => true);
}

  6. 在Main方法中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
static void Main(string[] args)
{
 
    UserBLL userBll = new UserBLL();
    userBll.InsertSomeData();
    var users = userBll.Select();
    foreach (var user in users)
    {
        Console.WriteLine(user.UserName + "是湖北人");
    };
    userBll.DeleteAll();
}

  7. 最后执行程序,打印如下信息:

李四是湖北人
赵六是湖北人

   1) 普通实现

  普通方式实现不想多讲,直接贴代码,看看与linq方式有什么区别:

  最后,我们通过这段代码输出全部用户资料信息的BJSON格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
/// 打印数据BJSON
/// </summary>
public void PrintBJSON()
{
    string BJSON = string.Empty;
    foreach (var documet in mongoCollection.FindAll().Documents)
    {
 
        BJSON += documet.ToString();
 
    }
    Console.WriteLine(BJSON);
}

  结果如下:

1
2
3
4
{ "UserId": "1001", "UserName": "张三", "PassWord": "123456", "_id": "4d80ec1ab8a4731338000001" }
{ "UserId": "1002", "UserName": "李四", "PassWord": "123456", "Detail": { "Address": "湖北", "Age": 20, "Email": "lisi@163.com" }, "_id": "4d80ec1ab8a4731338000002" }
{ "UserId": "1003", "UserName": "王五", "PassWord": "123456", "Detail": { "Address": "广东", "Age": 20, "Email": "wangwu@163.com" }, "_id": "4d80ec1ab8a4731338000003" }
{ "UserId": "1004", "UserName": "赵六", "PassWord": "123456", "Detail": { "Address": "湖北" }, "_id": "4d80ec1ab8a4731338000004" }

二、包含“子集合”的集合操作

  同样举个例子:有一个学校人事管理系统要统计班级和学生的信息,现在定义了一个“班级集合”,这个集合里面的学生字段是一个“学生集合”,包含了本班全部学生。

   1) linq方式实现

  基础配置我就不多说了,数据类定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// <summary>
/// 班级信息
/// </summary>
public class ClassInfo
{
    public string ClassName { get; set; }
    public List<Student> Students { get; set; }
}
 
/// <summary>
/// 学生信息
/// </summary>
public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
}

  查询叫“张三”的学生在哪个班级,以及他的详细信息:

(这里其实是ToList后在内存中查的,linq方式直接查询好像驱动不支持。)

1
2
3
4
public List<ClassInfo> Select()
{
    return mongoCollection.Linq().ToList().Where(x => x.Students.Exists(s => s.Name == "张三")).ToList();
}

   1) 普通实现

  查询叫“张三”的学生在哪个班级,以及他的详细信息:

1
2
3
4
5
public List<Document> Select()
{
    var mongocollection = mongoDatabase.GetCollection("ClassInfo");
    return mongocollection.Find(new Document { { "Students.Name", "张三" } }).Documents.ToList();
}

  打印数据的BJSON:

1
2
3
{ "_id": "4d814bae5c5f000000005f63", "ClassName": "1001", "Students": [ { "Name": "张三", "Age": 10 }, { "Name": "李四", "Age": 0 } ] }
{ "_id": "4d814bae5c5f000000005f64", "ClassName": "1002", "Students": [ ] }
{ "_id": "4d814bae5c5f000000005f65", "ClassName": "1003", "Students": [ { "Name": "王五", "Age": 11 }, { "Name": "赵六", "Age": 9 } ] }

三、小结

  通过本节例子我们发现,MongoDB有它独特的文档结构可以描述数据对象之间的一些关系特征。它虽然没有关系型数据库多表符合查询那样强大的表间查询方式,但也可以通过文档结构描述更灵活的关系特性,可以这么说,关系型数据库能做的,MongoDB基本上也可以做到。甚至有些关系数据库不容易做到的,MongoDB也可以轻松做到,比如,描述数据类的继承关系等。

MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系的更多相关文章

  1. MongoDB学习笔记:Python 操作MongoDB

    MongoDB学习笔记:Python 操作MongoDB   Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...

  2. MongoDB学习笔记一:MongoDB的下载和安装

    MongoDB学习笔记一:MongoDB的下载和安装 趁着这几天比較空暇,准备学习一下MongoDB数据库.今天就简单的学习了一些MongoDB的下载和安装.并创建了存储MongoDB的数据仓库. 将 ...

  3. MongoDB学习(操作集合中的文档)

    文档概念 文档的数据结构和JSON基本一样. 所有存储在集合中的数据都是BSON格式. BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON. 插入文档 insert()方法 ...

  4. MongoDB学习笔记一:MongoDB基础

    目录 MongoDB是什么? 学了有什么用? MongoDB入门 安装 修改数据库位置 MongoDB的启动方式 MongoDB的图形化工具 MongoDB基本命令 增 查询 更新 删除 排序 投影 ...

  5. MongoDB学习笔记四—增删改文档下

    $slice 如果希望数组的最大长度是固定的,那么可以将 $slice 和 $push 组合在一起使用,就可以保证数组不会超出设定好的最大长度.$slice 的值必须是负整数. 假设$slice的值为 ...

  6. Mongodb学习笔记四(Mongodb聚合函数)

    第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...

  7. MongoDB学习笔记四:索引

    索引就是用来加速查询的.创建数据库索引就像确定如何组织书的索引一样.但是你的优势是知道今后做何种查询,以及哪些内容需要快速查找.比如:所有的查询都包括"date"键,那么很可能(至 ...

  8. MongoDB 学习笔记四 C#调用MongoDB

    驱动 下载 https://github.com/mongodb/mongo-csharp-driver/downloads 项目地址: https://github.com/mongodb/mong ...

  9. MongoDB学习笔记(1):MongoDB简介

    1. MongoDB的特点: (1) 易于使用 MongoDB是一个面向文档的数据库,非关系型数据库.通过在文档中嵌入式文档和数据,面向对象的方法能够仅使用一条记录来表现复杂的层次关系.文档的键和值不 ...

随机推荐

  1. Genymotion Unable to create Virtual Device:Connection timeout

    1.进入C:\Users\[UserName]\AppData\Local\Genymobile,打开genymotion.log,找到最后几句话:     九月 2 14:29:45 [Genymo ...

  2. springmvc中使用response的out.print问题

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws E ...

  3. cocos2dx CCLabelTTF自己定义字体的使用

    版本号:  cocos2d-x 2.1.4 平台:  iOS 1. 字体文件名称 最好用字体冊中的family name.ttf, 不然字体可能不生效. 2. 在Info.plist  Fonts P ...

  4. python2.7 串口操作方式 编译 .py为windows可运行exe文件

    一 python操作串口 首先下载安装串口模块pyserial . 代码实现: import serial ser = serial.Serial('/dev/ttyUSB2', 115200) pr ...

  5. SuperSocket源码解析之启动过程

    一 简介 这里主要说明从配置系统引导启动SuperScoekt作为应用程序,且以控制台程序方式启动 二 启动过程 2.1 配置解析 从读取配置文件开始,直接拿到一个SocketServiceConfi ...

  6. SuperSocket源码解析之会话生命周期

    一 基本概念 会话(Session)是客户端与服务器进行通信的基本单元,也是一个Socket的封装,在http协议中也有Session机制,其主要作用封装一个通信单元socket,负责服务器与客户端消 ...

  7. Qt学习之路(60): 创建shared library

    前段时间说了Qt一些类库的使用,今天来换一下口味,来看一下程序设计的问题.今天来说的是关于共享库 shared library. 如果你打开一些 Windows 应用程序的目录,你会发现有很多程序的 ...

  8. 2016年会成为Java EE微服务年吗?

    原文  http://www.infoq.com/cn/news/2016/02/javaee-microservices 进入2016年时间还不是很长,让我们回顾下去年年底的一个预言.去年12月,来 ...

  9. 【Bootstrap3.0建站笔记一】表单元素排版

    1.文字和输入框前后排列: 代码: <div class="row"> <div class="col-lg-12"> <div ...

  10. PHP - 自定义函数

    第7章 自定义函数 学习要点: 1.标准函数 2.自定义函数 3.文件包含 4.魔法常量 一般来讲,冗余的代码都是不好的.一而再,再而三地重写代码不仅浪费时间,从布局结构角度看也显得粗制滥造.与所有优 ...