一、创建测试库、测试表、添加测试数据
使用之前文章提到的MongoDB Compass用法分别添加数据库[myDb]和集合(表)[userinfos]信息,
参考链接为:MongoDB Compass的安装及使用图文说明(非常详细),同时数据库连接语句也可从MongoDB Compass中获得
使用mongo shell命令添加测试数据
添加完成,MongoDB Compass中可看到已添加的数据
二、新建ASP.NET Core Web API项目
1、使用NuGet包管理器添加MongoDB.Driver
2、编写demo示例
1)插入
向myDb.userinfos中插入一条数据
/// <summary> /// 插入数据demo(仅可执行一次) /// </summary> [HttpGet, HttpPost] public void InsertDemo() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // 待添加的document // 待添加的document var doc = new BsonDocument { { "_id", 7 }, { "name", "吴九" }, { "age", 29 }, { "ename", new BsonDocument { { "firstname", "jiu" }, { "lastname", "wu" } } } }; // InsertOne() 添加单条document mycollection.InsertOne(doc); // 添加多条document //mycollection.InsertMany(IEnumerable<BsonDocument> docs); }
在MongoDB compass中可以看到新增的数据
2)查询
① 简单查询
/// <summary> /// 简单查询(Find) /// </summary> [HttpGet, HttpPost] public void SearchByFindOrFilter() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // Filter用于过滤,如查询name = '吴九' 的第一条记录 var filter = Builders<BsonDocument>.Filter; // Find(Filter)进行查询 var doc = mycollection.Find(filter.Eq("name", "吴九")).FirstOrDefault(); Console.WriteLine("简单查询结果:" + doc); }
简单查询结果为:
② AND查询
/// <summary> /// AND查询 /// </summary> [HttpGet, HttpPost] public void SearchByAnd() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // 查询年龄大于25且小于28的记录 var filter = Builders<BsonDocument>.Filter; var docs = mycollection.Find(filter.Gt("age", 25) & filter.Lt("age", 28)).ToList(); Console.WriteLine("AND查询结果:" + d) docs.ForEach(d => Console.WriteLine(d)); }
AND查询结果为:
③ OR查询
/// <summary> /// OR查询 /// </summary> [HttpGet, HttpPost] public void SearchByOr() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // 查询年龄小于25或大于28的记录 var filter = Builders<BsonDocument>.Filter; var docs = mycollection.Find(filter.Lt("age", 25) | filter.Gt("age", 28)).ToList(); Console.WriteLine("OR查询结果为:"); docs.ForEach(d => Console.WriteLine(d)); }
OR查询结果为:
④ 字段存在(Exists)
/// <summary> /// 字段存在(Exists) /// </summary> [HttpGet, HttpPost] public void SearchIsExists() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // 查询存在address字段的记录 var filter = Builders< BsonDocument>.Filter; var docs = mycollection.Find(filter.Exists("address")).ToList(); Console.WriteLine("存在address记录的查询结果为:"); docs.ForEach(d => Console.WriteLine(d)); }
字段存在(Exists)的查询结果为:
⑤ 排序(Sort)
/// <summary> /// 排序(Sort) /// </summary> [HttpGet, HttpPost] public void SearchWithSort() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // 查询age<26的记录,按年龄倒序排列 var filter = Builders <BsonDocument>.Filter; var sort = Builders <BsonDocument>.Sort; var docs = mycollection.Find(filter.Lt("age", 26)) // 过滤 .Sort(sort.Descending("age")) // 排序 .ToList(); Console.WriteLine("排序的查询结果为:"); docs.ForEach(d => Console.WriteLine(d)); }
排序(Sort)的查询结果为:
⑥ 查询指定字段(Projection)
/// <summary> /// 查询指定字段(Projection) /// </summary> [HttpGet, HttpPost] public void SearchWithSpecifyField() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); // 查询age<26的记录,包含name、age,排除 _id var filter = Builders<BsonDocument>.Filter; var project = Builders<BsonDocument>.Projection; var docs = mycollection.Find(filter.Lt("age", 26)) // 过滤 .Project(project.Include("name") // 包含name .Include("age") // 包含age .Exclude("_id")) // 包含_id .ToList(); Console.WriteLine("查询指定字段的查询结果为:"); docs.ForEach(d => Console.WriteLine(d)); }
查询指定字段(Projection)的查询结果为:
3)修改
① 修改单条记录(UpdateOne)
/// <summary> /// 修改单条记录(UpdateOne) /// </summary> [HttpGet, HttpPost] public void UpdateOneRecord() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument > ("userinfos"); var filter = Builders<BsonDocument>.Filter; var update = Builders<BsonDocument>.Update; var project = Builders<BsonDocument>.Projection; var docBefore = mycollection.Find(filter.Eq("name", "张三")).Project(project.Include("age").Include("name")).FirstOrDefault(); Console.WriteLine("修改前单条记录的结果为:" + docBefore); // 将张三的年龄改为18 mycollection.UpdateOne(filter.Eq("name", "张三"), update.Set("age", 18)); // 查询修改后张三的记录 var docAfter = mycollection.Find(filter.Eq("name", "张三")).Project(project.Include("age").Include("name")).FirstOrDefault(); Console.WriteLine("修改后单条记录的结果为:" + docAfter); }
修改单条记录的结果如下:
② 修改多条记录(UpdateMany)
/// <summary> /// 修改多条记录(UpdateMany) /// </summary> [HttpGet, HttpPost] public void UpdateManyRecord() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument>("userinfos"); var filter = Builders<BsonDocument>.Filter; var update = Builders<BsonDocument>.Update; var project = Builders<BsonDocument>.Projection; var docBefore = mycollection.Find(filter.Empty).Project(project.Include("age").Include("name").Include("mark")) // 没有的列不会显示 .ToList(); Console.WriteLine("修改多条记录前的结果为:"); docBefore.ForEach(d => Console.WriteLine(d)); // 将所有年龄小于25的记录标记为young(如果没有mark字段会自动添加) UpdateResult result = mycollection.UpdateMany(filter.Lt("age", 25), update.Set("mark", "young")); if(result.IsModifiedCountAvailable) // 获取一个表示修改后的计数是否可用的值 { Console.WriteLine($ "符合条件的有{result.MatchedCount}条记录,"); Console.WriteLine($ "一共修改了{result.ModifiedCount}条记录。"); // 查询修改后的记录 var docs = mycollection.Find(filter.Empty).Project(project.Include("age").Include("name").Include("mark")).ToList(); Console.WriteLine("修改多条记录后的结果为:"); docs.ForEach(d => Console.WriteLine(d)); } else { Console.WriteLine("无修改操作!"); } }
修改多条记录(UpdateMany)的结果为:
4)删除
① 删除单条记录(DeleteOne)
/// <summary> /// 删除单条记录(DeleteOne) /// </summary> [HttpGet, HttpPost] public void DeleteOneRecord() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument> ("userinfos"); var filter = Builders<BsonDocument>.Filter; var project = Builders<BsonDocument>.Projection; var docBefore = mycollection.Find(filter.Empty).Project(project.Include("age").Include("name").Include("mark")).ToList(); Console.WriteLine("删除张三前的记录的结果为:"); docBefore.ForEach(d => Console.WriteLine(d)); // 删除名字为张三的记录 mycollection.DeleteOne(filter.Eq("name", "张三")); // 查询删除张三后的记录 var docs = mycollection.Find(filter.Empty).Project(project.Include("age").Include("name").Include("max")).ToList(); Console.WriteLine("删除张三后的记录的结果为:"); docs.ForEach(d => Console.WriteLine(d)); }
删除单条记录(DeleteOne)的结果为:
② 删除多条记录(DeleteMany)
/// <summary> /// 删除多条记录(DeleteMany) /// </summary> [HttpGet, HttpPost] public void DeleteManyRecord() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<BsonDocument> ("userinfos"); var filter = Builders<BsonDocument>.Filter; var project = Builders<BsonDocument>.Projection; var docBefore = mycollection.Find(filter.Empty).Project(project.Include("age").Include("name").Include("mark")).ToList(); Console.WriteLine("删除所有年龄大于25岁的记录前的结果为:"); docBefore.ForEach(d => Console.WriteLine(d)); // 删除所有年龄大于25岁的记录 DeleteResult result = mycollection.DeleteMany(filter.Gt("age", 25)); Console.WriteLine($ "一共删除了{result.DeletedCount}条记录"); // 查询删除所有年龄大于25岁的记录 var docs = mycollection.Find(filter.Empty).Project(project.Include("age").Include("name").Include("max")).ToList(); Console.WriteLine("删除所有年龄大于25岁的记录后的结果为:"); docs.ForEach(d => Console.WriteLine(d)); }
删除多条记录(DeleteMany)的结果为:
5)类型映射
① 查询结果映射到实体类示例
mongoDB支持自动映射,直接使用泛型即可
/// <summary> /// 查询结果映射到实体类示例 /// </summary> [HttpGet, HttpPost] public void TypeMappingDemo() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<Userinfo>("userinfos"); var filter = Builders<Userinfo>.Filter; var sort = Builders<Userinfo>.Sort; List<Userinfo> userinfos = mycollection.Find(filter.Lte("age", 25)) // 查询年龄小于等于25岁的记录 .Sort(sort.Descending("age")) // 按年龄进行倒序 .ToList(); // 遍历结果 userinfos.ForEach(u => Console.WriteLine($ "姓名:{u.name},年龄:{u.age},英文名:{u.ename.firstname} {u.ename.lastname}")); Console.ReadKey(); }
用户信息类
/// <summary> /// 用户信息类 /// </summary> public class Userinfo { /// <summary> /// id /// </summary> public int _id { get; set; } /// <summary> /// 姓名 /// </summary> public string name { get; set; } /// <summary> /// 年龄 /// </summary> public int age { get; set; } /// <summary> /// 等级 /// </summary> public int level { get; set; } /// <summary> /// 英文名 /// </summary> public Ename ename { get; set; } /// <summary> /// 角色 /// </summary> public string[] roles { get; set; } /// <summary> /// 地址 /// </summary> public string address { get; set; } /// <summary> /// 标记 /// </summary> public string mark { get; set; } }
英文名类
/// <summary> /// 英文名 /// </summary> public class Ename { /// <summary> /// 名 /// </summary> public string firstname { get; set; } /// <summary> /// 姓 /// </summary> public string lastname { get; set; } }
查询结果映射到实体类示例的结果为:
② 查询结果映射到实体类示例 - 常用属性修改上方代码
上边的例子仅仅用了基本的自动化映射,使用基本的自动化映射时:类和Bson中的字段必须严格一致(_id除外,可以自动映射到_id/id/Id),且Bson中的每一个字段在实体类中都必须有一个对应的字段,不然就会抛出异常,这就造成我们可能要写一个非常庞大的实体类,而且类中的字段命名也要严格和Bson中的字段一致。这些限制对我们开发来说是不能接受的,这里我们采用mongoDriver中的一些属性改进一下上边的代码,如下:
/// <summary> /// 查询结果映射到实体类示例 - 常用属性修改上方代码 /// </summary> [HttpGet, HttpPost] public void TypeMappingWithCommonAttributes() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var mycollection = mydb.GetCollection<UserinfoBson>("userinfos"); var filter = Builders<UserinfoBson>.Filter; var sort = Builders<UserinfoBson>.Sort; List<UserinfoBson> userinfos = mycollection.Find(filter.Lte("age", 25)) // 查询年龄小于等于25岁的记录 .Sort(sort.Descending("age")) // 按年龄进行倒序 .ToList(); // 遍历结果 userinfos.ForEach(u => { Console.WriteLine($ "编号:{u.userId},姓名:{u.name},年龄:{u.age},英文名:{u.ename?.ming} {u.ename.xing},性别:{u.gender}"); Console.WriteLine($ "其他属性:{u.otherprops}"); Console.WriteLine(); }); Console.ReadKey(); }
用户信息类 - Bson
/// <summary> /// 用户信息类 - Bson /// </summary> public class UserinfoBson { /// <summary> /// id /// </summary> [BsonId] // BsonId修饰的字段对应BsonDocument中的_id; public int userId { get; set; } /// <summary> /// 姓名 /// </summary> public string name { get; set; } /// <summary> /// 年龄 /// </summary> public int age { get; set; } /// <summary> /// 英文名 /// </summary> public EnameBson ename { get; set; } /// <summary> /// 性别 /// </summary> [BsonDefaultValue('男')] // BsonDefaultValue(value)用于指定默认值; public char gender { get; set; } /// <summary> /// 昵称 /// </summary> [BsonIgnore] // BsonIgnore表示不映射,即使BsonDocument中包含该字段也不会赋值给属性; public string nickname { get; set; } /// <summary> /// 其他属性 /// </summary> [BsonExtraElements] // BsonExtraElements修饰的字段用于存储没有映射到类中的其他属性; public BsonDocument otherprops { get; set; } }
英文名类 - Bson
/// <summary> /// 英文名 - Bson /// </summary> public class EnameBson { /// <summary> /// 名 /// </summary> [BsonElement("firstname")] // BsonElement可以指定修饰的属性映射到BsonDocument中的哪个字段 public string ming { get; set; } /// <summary> /// 姓 /// </summary> [BsonElement("lastname")] public string xing { get; set; } }
查询结果映射到实体类示例 - 常用属性修改上方代码的结果为:
6)使用LINQ查询
① 基本查询:查找年龄大于22岁的学生;② 连接查询:查询各个学生的学号、姓名、班级名
/// <summary> /// 使用LINQ查询 /// </summary> [HttpGet, HttpPost] public void LINQQuery() { // 连接数据库 var client = new MongoClient("mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false"); // 获取DataBase var mydb = client.GetDatabase("myDb"); // 获取Collection var stuCollection = mydb.GetCollection<Student> ("students"); var clsCollection = mydb.GetCollection <Classx> ("classes"); //查找年龄大于22的学生 Console.WriteLine("-------------查找年龄大于22的学生列表--------------"); //1.query语法 List<Student> stuList1 = (from stu in stuCollection.AsQueryable() where stu.age > 22 select stu).ToList(); //2.点语法 List<Student> stuList2 = stuCollection.AsQueryable().Where(s => s.age > 22).ToList(); stuList1.ForEach(stu => Console.WriteLine($ "姓名:{stu?.stuName}, 年龄:{stu?.age}")); Console.WriteLine(); //表连接查询,查询各个学生的班级名 Console.WriteLine("-------------表连接,查询学生的班级名----------------"); //1.query语法 var result1 = from stu in stuCollection.AsQueryable() join cls in clsCollection.AsQueryable() on stu.classNo equals cls.no select new { stuno = stu.no, stu.stuName, cls.clsName }; //2.点语法 var result2 = stuCollection.AsQueryable().Join(clsCollection.AsQueryable(), stu => stu.classNo, cls => cls.no, (stu, cls) => new { stuno = stu.no, stu.stuName, cls.clsName }); //遍历结果 foreach(var item in result1) { Console.WriteLine($ "学号:{item.stuno}, 姓名:{item.stuName}, 班级:{item.clsName}"); } Console.ReadKey(); }
学生类
/// <summary> /// 学生类 /// </summary> public class Student { /// <summary> /// 学号 /// </summary> public int no { get; set; } /// <summary> /// 姓名 /// </summary> public string stuName { get; set; } /// <summary> /// 年龄 /// </summary> public int age { get; set; } /// <summary> /// 班级编号 /// </summary> public int classNo { get; set; } /// <summary> /// 其他 /// </summary> [BsonExtraElements] public BsonDocument others { get; set; } }
班级类
/// <summary> /// 班级类 /// </summary> public class Classx { /// <summary> /// 班级编号 /// </summary> public int no { get; set; } /// <summary> /// 班级名 /// </summary> public string clsName { get; set; } /// <summary> /// 其他 /// </summary> [BsonExtraElements] public BsonDocument others { get; set; } }
查找年龄大于22岁的学生以及查询各个学生的学号、姓名、班级名的结果如下:
三、附录
1、userinfos表测试数据
use myDb db.userinfos.insertMany([ {_id:1, name: "张三", age: 23,level:10, ename: { firstname: "san", lastname: "zhang"}, roles: ["vip","gen" ]}, {_id:2, name: "李四", age: 24,level:20, ename: { firstname: "si", lastname: "li"}, roles:[ "vip" ]}, {_id:3, name: "王五", age: 25,level:30, ename: { firstname: "wu", lastname: "wang"}, roles: ["gen","vip" ]}, {_id:4, name: "赵六", age: 26,level:40, ename: { firstname: "liu", lastname: "zhao"}, roles: ["gen"] }, {_id:5, name: "田七", age: 27, ename: { firstname: "qi", lastname: "tian"}, address:'北京' }, {_id:6, name: "周八", age: 28,roles:["gen"], address:'上海' } ])
2、student表测试数据
db.students.insertMany([ {"no":1, "stuName":"jack", "age":23, "classNo":1}, {"no":2, "stuName":"tom", "age":20, "classNo":2}, {"no":3, "stuName":"hanmeimei", "age":22, "classNo":1}, {"no":4, "stuName":"lilei", "age":24, "classNo":2} ])
3、classs表测试数据
db.classes.insertMany([ {"no" : 1,"clsName" : "A班"}, {"no" : 2,"clsName" : "B班"} ])