MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系
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 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的文档结构描述数据关系的更多相关文章
- MongoDB学习笔记:Python 操作MongoDB
MongoDB学习笔记:Python 操作MongoDB Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...
- MongoDB学习笔记一:MongoDB的下载和安装
MongoDB学习笔记一:MongoDB的下载和安装 趁着这几天比較空暇,准备学习一下MongoDB数据库.今天就简单的学习了一些MongoDB的下载和安装.并创建了存储MongoDB的数据仓库. 将 ...
- MongoDB学习(操作集合中的文档)
文档概念 文档的数据结构和JSON基本一样. 所有存储在集合中的数据都是BSON格式. BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON. 插入文档 insert()方法 ...
- MongoDB学习笔记一:MongoDB基础
目录 MongoDB是什么? 学了有什么用? MongoDB入门 安装 修改数据库位置 MongoDB的启动方式 MongoDB的图形化工具 MongoDB基本命令 增 查询 更新 删除 排序 投影 ...
- MongoDB学习笔记四—增删改文档下
$slice 如果希望数组的最大长度是固定的,那么可以将 $slice 和 $push 组合在一起使用,就可以保证数组不会超出设定好的最大长度.$slice 的值必须是负整数. 假设$slice的值为 ...
- Mongodb学习笔记四(Mongodb聚合函数)
第四章 Mongodb聚合函数 插入 测试数据 ;j<;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, ...
- MongoDB学习笔记四:索引
索引就是用来加速查询的.创建数据库索引就像确定如何组织书的索引一样.但是你的优势是知道今后做何种查询,以及哪些内容需要快速查找.比如:所有的查询都包括"date"键,那么很可能(至 ...
- MongoDB 学习笔记四 C#调用MongoDB
驱动 下载 https://github.com/mongodb/mongo-csharp-driver/downloads 项目地址: https://github.com/mongodb/mong ...
- MongoDB学习笔记(1):MongoDB简介
1. MongoDB的特点: (1) 易于使用 MongoDB是一个面向文档的数据库,非关系型数据库.通过在文档中嵌入式文档和数据,面向对象的方法能够仅使用一条记录来表现复杂的层次关系.文档的键和值不 ...
随机推荐
- setitimer()函数使用
setitimer()为Linux的API,并非C语言的Standard Library,setitimer()有两个功能,一是指定一段时间后,才执行某个function,二是每间格一段时间就执行某个 ...
- JSpider是一个用Java实现的WebSpider
JSpider是一个用Java实现的WebSpider,JSpider的执行格式如下: jspider [URL] [ConfigName] URL一定要加上协议名称,如:http://,否则会报错. ...
- iOS 使用SBJSON创建和解析JSON
原文地址:http://blog.csdn.net/gf771115/article/details/7718403 //创建JSON NSDictionary *dictonary = [[NSMu ...
- Java 判断多级路径是否存在,不存在就创建
第一种方案: /** * 是否创建目录 * @param path * @return */ public boolean isexitsPath(String path)throws Interru ...
- 【项目分析】利用C#改写JAVA中的Base64.DecodeBase64以及Inflater解码
原文:[项目分析]利用C#改写JAVA中的Base64.DecodeBase64以及Inflater解码 最近正在进行项目服务的移植工作,即将JAVA服务的程序移植到DotNet平台中. 在JAVA程 ...
- Mysql主从配置+读写分离(转)
MySQL从5.5版本开始,通过./configure进行编译配置方式已经被取消,取而代之的是cmake工具.因此,我们首先要在系统中源码编译安装cmake工具. 注:安装前须查看是否已经安装了 ...
- php 上传文件代码
通过 PHP,能够把文件上传到server.里面加入一些图片的推断,假设不加推断文件的类型就能够上传随意格式的文件. 为了站点的安全,肯定不让上传php文件,假设有人进入你的后台,上传了一个php文件 ...
- Cocos2d-x CCTableView实现列表
在ios程序设计中,会大量使用到tableview视图(UITableView),那么在cocos2d-x中,如果需要类似的列表,该如何实现呢?在引擎中参照ios中的UITableView实现了一个叫 ...
- PHP - 接口 - 单一接口
/* * 接口的使用 */ //定义接口 interface IPerosn{ public function eat(); public function water(); } //定义继承自接口的 ...
- 前端面试题整理(css)
1.介绍所知道的CSS hack技巧(如:_, *, +, \9, !important 之类). CSS hack的原理: 由于不同的浏览器和浏览器各版本对CSS的支持及解析结果不一样,以及CSS优 ...