MongoDB数据库介绍并用.NET Core对其进行编码

2022-07-15,,,,

浅入 mongodb

monogodb 是什么

mongodb 是 nosql 型数据库,主要特征是存储结构化数据,mongodb 是基于分布式文件存储的开源数据库系统。

结构化数据

以往我们使用 mysql、sqlserver 等数据库,数据都是一条条的。mongodb 的结构化数据正是区别于这种列-行式的数据。

结构化数据具有层级关系:

例如:

{
     name: "mongodb",
     type: "database",
     count: 1,
     info: {
         x: 203,
         y: 102
     }
}

mongodb 与关系型数据库

由于 mongodb 中,没有表、行、列,因此初学 mongodb 时可能会有困扰,这里给出一些 mongodb 与 普通sql数据库对应的术语。

sql术语/概念 mongodb术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins   非关系型数据库,表与表之间没关系
primary key primary key 主键,mongodb自动将_id字段设置为主键

资料来源:https://www.runoob.com/mongodb/mongodb-databases-documents-collections.html

mongodb 入门命令

使用 mongo 进入 mongodb shell 后,可使用命令(相当于sql)执行操作。

注: mongodb 中,有一个自动的 _id 字段,此字段 mongodb 自动设置为主键并自动生成值。

显示所有数据库(包含系统数据库):

show dbs

当前正在操作的数据库或集合:

db

连接到指定数据库:

use {数据库名称}

显示所有集合:

show collections
# 或
show tables

查看集合中的所有文档:

# mycollection 是集合名称
db.getcollection("mycollection").find()
db.getcollection("mycollection").find().limit(1000).skip(0)

可能你不信,笔者百度了很久,第一页没找到一篇合适的友好的 "mongodb 查看集合中的所有文档",特别是 csdn 的垃圾文真的多。建议别瞎折腾了,去下一个 navicat premium,操作的时候,底部会提示所用的命令。

另外 mongodb 有很多实用工具:https://docs.mongodb.com/tools/

文档

mongodb 中的文档(document)即关系型数据库中的一条记录(row)、一行数据。

但, mongodb 中,一个集合(collection-table)中,是不需要具有相同字段的。例如:

a 文档:

{
     name: "mongodb",
     type: "database",
     count: 1,
     info: {
         x: 203,
         y: 102
     }
}

b 文档:

{
     name: "mongodb",
     typename: "database",
     datacount: 1,
     datainfo: {
         m: 203,
         n: 102
     }
}

.net core 示例

我们从一个基础模板开始。

创建一个控制台程序,打开 nuget 搜索并安装 mongodb.driver

            var client = new mongoclient("mongodb://{mongodb}:27017");
            imongodatabase database = client.getdatabase("test");

集合

可以通过 createcollection() 或 createcollectionasync() 创建一个集合,跟普通数据库不同的是,创建集合时是不需要指定结构的,只需要指定名称即可:

await database.createcollectionasync("test");

获取集合

getcollection() 函数可以让我们获取到集合,如果集合不存在,则会自动创建。

imongocollection<tdocument> getcollection<tdocument>()

由于同一个集合可以有不同字段和字段类型的文档,因此几个文档如果有所差别,是很难统一起来的,例如:

(n/a) 代表此文档没有这个字段;如果一个文档有 10 个字段,另一个文档有 8 个字段,但是两者的字段完全不同时,要合并起来来,就有 18 个字段了。很明显,不应该汇集在一起,而是应该使用强类型对其 ”归档“ 。

创建两个类,分别为 test1,test2,其内容如下:

    public class test1
    {
        public string name { get; set; }
    }

    public class test2
    {
        public string datatype { get; set; }
    }

以两种文档类型获取集合:

            var collection1 = database.getcollection<test1>("test");
            var collection2 = database.getcollection<test2>("test");

这个获取集合的意思是,获取此集合中这类格式的文档的操作能力。

往集合中插入数据:

            collection1.insertone(new test1 { name = "test1" });
            collection2.insertone(new test2 { datatype = "test2" });
			// await collection.insertoneasync(object);

启动,查看结果。

insertmany() 可以插入批量数据:

            test1[] datas = new test1[]
            {
                new test1 { name = "test1" }
            };
            collection1.insertmany(datas);

统计数量

获取集合中所有的文档数:

collection1.countdocuments(new bsondocument())
// await collection1.countdocumentsasync(new bsondocument());

任意一个文档集合对象,使用 countdocuments(new bsondocument()) 都是获得此集合的所有文档数,而不是此类型的文档数。例如:

            var collection1 = database.getcollection<test1>("test");
            collection1.countdocuments(new bsondocument())

获取的并不是 test1 类型的文档数量,而是整个集合所有文档的数量。

原因是,countdocuments() 是一个过滤器函数,可以使用指定条件来筛选符合条件的文档的数量。指定条件后面会介绍

查询

mongodb 的查询并不像 linq 中的表达式,基础了 ienumerable或 ienumerable<t> 接口,因此驱动没有 whereselect 这种表达式的查询方法。

find() 函数是查询函数,里面可以添加丰富的表达式,来筛选文档,当数据加载到本地内存后,即可使用丰富的表达式。

bsondocument 是一个类型,代表了要查询的文档筛选条件,如果 bsondocument 对象没有添加任何属性,则代码没有筛选参数,则默认所有文档都符号条件。

我们把 test1 和 test2 类型,都加上一个属性:

        public objectid _id { get; set; }

不然会报格式化错误:system.formatexception

如何序列化文档

document 是文档对象, jsonserializer 是 system.text.json 的静态类。

console.writeline(jsonserializer.serialize(document));

查询第一条记录

var document = collection1.find(new bsondocument()).firstordefault();

不加条件可能导致的问题

以下代码会导致程序报错:

            var documents = await collection1.find(new bsondocument()).tolistasync();
            foreach(var item in documents)
            {
                console.writeline(jsonserializer.serialize(item));
            }

因为 collection1 是标记为 test1 的文档集合;但是 .find(new bsondocument()) 是查询集合中的所有文档,因此获取到 test2。

但是 test2 是不能转为 test1 的,因此,会导致程序报错。

查看所有文档

var documents = collection1.find(new bsondocument()).tolist();
var documents = await collection1.find(new bsondocument()).tolistasync();

前面已经说过,如果集合中存在其它格式的文档,获取全部文档时,因为 test2 跟 test1 没任何关系,会导致 mongodb.driver 报错。

如果文档数量比较大,要使用异步的 foreachasync() 查询,其原理是 回调。

            list<test1> tests = new list<test1>();
            action<test1> action = item =>
            {
                tests.add(item);
                console.writeline(jsonserializer.serialize(item));
            };

            await collection1.find(new bsondocument()).foreachasync(action);

查询结束

使用 find() 以及后续函数查询后,要结束查询(延迟加载),可以使用 tocursor() 函数结束,程序会立即开始查询并将数据返回内存。

转换查询

使用 toenumerable() 可以使用 linq 来查询文档。

var list = collection1.find(new bsondocument()).tocursor().toenumerable();

过滤器

前面我们查询的时候都使用 .find(new bsondocument())bsondocument 是过滤器对象,里面存储了过滤的规则,但是我们不能直接设置 new bsondocument()中的属性,而是使用构建器filterdefinitionbuilder对象,而此对象可以通过 mongodb.driver.builders<tdocument>.filter 创建 。

假设有以下数据集(文档):

5f8bdf88e63d14cb5f01dd85	小明	19
5f8bdf88e63d14cb5f01dd86	小红	20
5f8bdf88e63d14cb5f01dd87	小张	16
5f8bdf88e63d14cb5f01dd88	小小	17
    
# -----插入数据的代码-----
    public class test
    {
        public objectid _id { get; set; }
        public string name { get; set; }
        public int age { get; set; }
    }

            var datas = new test[]
            {
                new test{ name="小明",age=19},
                new test{ name="小红",age=20},
                new test{ name="小张",age=16},
                new test{ name="小小",age=17}
            };

            collection.insertmany(datas);

使用构建器:

filterdefinition<test> filter = builders<test>.filter

查询 age 大于 18 的文档:

filterdefinition<test> filter = filterbuilder.where(item => item.age >= 18);

获取结果:

test[] documents = collection.find(filter).toenumerable<test>().toarray();

过滤器还有 gt()in()lte() 等非 linq 的函数,需要查看文档学习。

builders<tdocument>

builders<tdocument> 除了能够生成过滤构建器,还有其它几种构建器:

		// 条件过滤
        public static filterdefinitionbuilder<tdocument> filter { get; }

		// 索引过滤
        public static indexkeysdefinitionbuilder<tdocument> indexkeys { get; }

		// 映射器,相当于使用 linq 的 .select() 查询自己只需要的字段
        public static projectiondefinitionbuilder<tdocument> projection { get; }

		// 排序,创建排序规则,如工具年龄排序
        public static sortdefinitionbuilder<tdocument> sort { get; }

		// 更新,更新某些字段的值等
        public static updatedefinitionbuilder<tdocument> update { get; }

详细请参考 https://mongodb.github.io/mongo-csharp-driver/2.10/reference/driver/definitions/#projections

名称映射

由于 mongodb 区分字段的大小写,文档的字段一般使用驼峰命名法,首字母小写,而 c# 字段属性首字母是 大小开头的,因此需要不同名称对应起来。

可以使用 bsonelement 特性来设置映射的名称。

class person
{
    [bsonelement("fn")]
    public string firstname { get; set; }

    [bsonelement("ln")]
    public string lastname { get; set; }
}

以上就是 mongodb 的初入门知识,但是使用了 mongodb 有什么好处?可以参考这篇文章:

整理场景如下:

  • 存储应用程序日志。日志结构化,查找方便,可以导出其它格式和二次利用。

  • 增加字段不需要改动表结构,灵活变更。

  • 支持 json 格式导入;类似 json 的数据结构;能够很容易还原对象的属性,一次性存储数据;如果使用传统数据库,则需要建立多个表并设置主键外界关系。

  • 集群。分布式集群海量数据,容易拓展;故障转移保证服务可用;

  • 解决分布式文件存储需求。

  • 索引方式灵活。

到此这篇关于mongodb数据库介绍并用.net core对其进行编码的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。

《MongoDB数据库介绍并用.NET Core对其进行编码.doc》

下载本文的Word格式文档,以方便收藏与打印。