1. 新建一个控制台项目
选择.net framework版本为4.6,最新的mongodb驱动nuget需要达到4.5.2以上,所以选择了4.6版本。
2. 引入nuget包
MongoDB.Driver和MongoDB.Bson
3. MongoDB连接配置
// 连接地址 string connectionStr = "mongodb://localhost:27017"; // 数据库名 string databaseName = "test"; // 表名 string dbName = "tests"; // 创建连接 var mongoClient = new MongoClient(connectionStr); var mongoDb = mongoClient.GetDatabase(databaseName); var collection = mongoDb.GetCollection<User>(dbName);
新建了一个user类
public class User { public string _id { get; set; } public int Age { get; set; } public string Name { get; set; } public User Son { get; set; } public DateTime BirthDateTime { get; set; } }
4. 简单增删改查
4.1 查询
4.1.1 根据filter字段来查
查询代码
// 过滤条件 var filter = Builders<User>.Filter.Eq(u => u.Name, "CeShi"); var filterALL = Builders<User>.Filter.Where(u => u._id != null); // 查询结果 var resultList = collection.Find(filterALL).ToList(); Console.WriteLine("查询结果"); int i = 1; foreach (var result in resultList) { Console.WriteLine($"//{i}"); Console.WriteLine("{"); Console.WriteLine($""id":"{result.id}","Age":"{result.Age}","Name":"{result.Name}","); Console.WriteLine(""Son":{"); if (result.Son != null && result.Son.Age > 0) { Console.WriteLine($""Age":"{result.Son.Age}","Name":"{result.Son.Name}""); } Console.WriteLine("},"); Console.WriteLine($""BirthDateTime":"{result.BirthDateTime}""); Console.WriteLine("}"); i++; }
第一种查询eq方式为根据条件来查的,注意这个时候会区分大小写的。第二种filter是尝试查询全部数据,但是没有找到相关方法,写的一个代替品,因为_id的值是肯定有的,所以这么写了。
第一中查询方式结果
第二种where查询结果
4.1.2 使用linq的方式也可以进行查询
进行全部查询,如
//var query = from u in collection.AsQueryable() // select new { u.Name, u.age }; var query = from u in collection.AsQueryable() select u; var resultList = query.ToList();`
这样查出的结果如下
在linq里可以使用where条件来过滤数据
查询子文档中的数据
4.2 新增
4.2.1 添加一条数据
// 自定义主键 var id = Guid.NewGuid().ToString(); // 要添加的数据实体 var user = new User { _id = id, Age = 26, Name = "CeShi", Son = new User { Age = 1, Name = "ceshi" }, BirthDateTime = DateTime.Now }; //添加一条数据 collection.InsertOne(user);`
4.2.2 添加多条数据
List<User> userListAdd = new List<User>(); User userAdd1 = new User { _id = Guid.NewGuid().ToString(), Age = 23, Name = "zhangsan", BirthDateTime = DateTime.Now.AddYears(-22) }; userListAdd.Add(userAdd1); User userAdd2 = new User { _id = Guid.NewGuid().ToString(), Age = 33, Name = "Adamas", Son = new User { Age = 3, Name = "Adams", BirthDateTime = DateTime.Now.AddYears(-2) }, BirthDateTime = DateTime.Now.AddYears(-32) }; userListAdd.Add(userAdd2); // 添加多条使用 InsertMany()方法 collection.InsertMany(userListAdd);
4.3 修改更新
4.3.1 简单更新
使用主键或其他字段进行更新,如将Name为zhagnsan的son赋值
var filter = Builders<User>.Filter.Eq("Name", "zhangsan"); var son = new User { Age = 2, Name = "zhangxiao", BirthDateTime = DateTime.Now.AddYears(-1) }; // 更新数据 var update = Builders<User>.Update.Set("Son", son); // 执行更新操作 更新一条数据 UpdateResult upResult = collection.UpdateOne(filter, update); // 得到更新数据条数 var upCount = upResult.ModifiedCount;`
结果如下
如果想更新多条数据,则配合查询条件,使用collection.UpdateMany
// 过滤条件 var filter = Builders<User>.Filter.Where(u=>u.Name== "CeShi"); // 更新数据 var update = Builders<User>.Update.Set("age", "25"); // 执行更新操作 更新多条 UpdateResult upResult = collection.UpdateMany(filter, update); // 得到更新数据条数 var upCount=upResult.ModifiedCount;
4.3.2 根据子集合属性更新
根据son的Name的值为“zhangxiao”,将他的年龄修改为4
// 过滤条件 var filter = Builders<User>.Filter.Where(u=>u.Son.Name== "zhangxiao"); var son = new User { Age = 4, Name = "zhangxiao", BirthDateTime = DateTime.Now.AddYears(-3) }; // 更新数据 var update = Builders<User>.Update.Set("Son", son); // 执行更新操作 更新一条数据;更新多条,使用UpdateMany UpdateResult upResult = collection.UpdateOne(filter, update); // 得到更新数据条数 var upCount = upResult.ModifiedCount;`
结果如下
4.4 删除
4.4.1 根据主键或其他条件删除
将name为“CeShi”的数据删除
var filter = Builders<User>.Filter.Where(u => u.Name == "CeShi"); // 删除一条数据 DeleteResult deResult = collection.DeleteMany(filter); // 得到删除条数 var deCount = deResult.DeletedCount; Console.WriteLine($"删除条数{deCount.ToString()}");
结果查询,已经将name为“CeShi”的数据删除了
4.4.2 根据子集合属性删除
删除子文档son里name为“zhangxiao”的数据
var filter = Builders<User>.Filter.Where(u => u.Son.Name == "zhangxiao"); // 删除一条数据 DeleteResult deResult = collection.DeleteMany(filter); // 得到删除条数 var deCount = deResult.DeletedCount; Console.WriteLine($"删除条数{deCount.ToString()}");
结果查询,已经没有子文档son里name为“zhangxiao”的数据了
5. MongoDB命令对应的操作
5.1 $project
$project类似于sql中的select,筛选出我们要的显示字段,如我们想选出所有数据的Name和Age字段
var query = from p in collection.AsQueryable() select new { p.Name, p.Age }; // 或者 //var query = collection.AsQueryable() // .Select(p => new { p.Name, p.Age });
结果如下
5.2 $sort
排序。我们根据年龄降序和姓名升序的方式查找数据
var query = from p in collection.AsQueryable() orderby p.Name, p.Age descending select p; // 或者 //var query = collection.AsQueryable() .OrderBy(p => p.Name).ThenByDescending(p => p.Age);
结果如下
5.3 $limit
类似于linq中的take,选取多少条数据
var query = collection.AsQueryable().Take(2);
结果如下
5.4 $skip
类似于linq下的skip,跳过m条数据,配合take使用,即跳过m条数据取n条数据
var query = collection.AsQueryable().Skip(1).Take(1);
结果如下
5.5 $group
分组
var query = from p in collection.AsQueryable() group p by p.Age into g select new { Age = g.Key, Count = g.Count() }; // 或者 //var query = collection.AsQueryable() // .GroupBy(p => p.Age ) // .Select(g => new { Age = g.Key, Count = g.Count() });
结果如下
5.6 $lookup 表联合查询
类似于ef中的左连接
var query = from u in collect.AsQueryable() join o in coll.AsQueryable() on u.Name equals o.Name select new { u._id, u.son, o.Id,o.Name }; var result = query.ToList();
由于测试库没有建立第二张表,就简单放一下测试语句
5.7 Distinct
去重。我们查询年龄去重的值
var query = collection.AsQueryable() .Select(p => new { p.Age }) .Distinct();
结果如下
5.8 其他
请自行参照官方文档,官方文档网址:https://docs.mongodb.com/v3.4/reference/operator/query/
6 c#操作Mongo查询
6.1 插入表结构
新建类
class BsonDocument { public ObjectId _id { get; set; } public string Item { get; set; } public int Num { get; set; } public List<ArrayDocument> Instock { get; set; } } public class ArrayDocument { public string WareHouse { get; set; } public string Qty { get; set; } }
插入数据库
var documents = new[] { new BsonDocument{ Item="journal", Num=15, Instock=new List<ArrayDocument>(){ new ArrayDocument { WareHouse = "A", Qty = "5" }, new ArrayDocument { WareHouse = "C", Qty = "15" } } }, new BsonDocument{ Item="notebook", Num=5, Instock=new List<ArrayDocument>(){ new ArrayDocument { WareHouse = "C", Qty = "5" } } }, new BsonDocument{ Item="paper", Num=30, Instock=new List<ArrayDocument>(){ new ArrayDocument { WareHouse = "A", Qty = "60" }, new ArrayDocument { WareHouse = "B", Qty = "15" } } } , new BsonDocument{ Item="planner", Num=22, Instock=new List<ArrayDocument>(){ new ArrayDocument { WareHouse = "A", Qty = "40" }, new ArrayDocument { WareHouse = "B", Qty = "5" } } }, new BsonDocument{ Item="postcard", Num=2, Instock=new List<ArrayDocument>(){ new ArrayDocument { WareHouse = "B", Qty = "15" }, new ArrayDocument { WareHouse = "C", Qty = "35" } } } }; collection.InsertMany(documents);
6.2 普通查询
6.2.1 查询指定item的值
代码
var filter = Builders<BsonDocument>.Filter.Eq("Item", "paper"); var result = collection.Find(filter).ToList();
结果
6.2.2 查询Num值大于1的
代码
var filter = Builders<BsonDocument>.Filter.Gt("Num", 1); var result = collection.Find(filter).ToList();
结果
6.2.3 and多条件查询
代码
//创建过滤器生成器对象 FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter; //创建过滤器 var filter = Builders<BsonDocument>.Filter.And(filterBuilder.Gt("Num", 1), filterBuilder.Eq("Item", "notebook")); var result = collection.Find(filter).ToList();
结果
6.2.4 or多条件查询
代码
//创建过滤器生成器对象 FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter; //创建过滤器 var filter = Builders<BsonDocument>.Filter.Or(filterBuilder.Gt("Num", 5), filterBuilder.Eq("Item", "notebook")); var result = collection.Find(filter).ToList();
结果
6.2.5 not查询
查找num小于10
代码
//创建过滤器生成器对象 FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter; //创建过滤器 var filter = Builders<BsonDocument>.Filter.Not(filterBuilder.Gt("Num", 10)); var result = collection.Find(filter).ToList();
结果
6.2.6 排序
代码
//排序规则 Ascending 正序 Descending 倒序 SortDefinition<BsonDocument> sort = Builders<BsonDocument>.Sort.Descending("Num"); var result = collection.Find(Builders<BsonDocument>.Filter.Empty).Sort(sort).ToList();
结果
6.2.6 in查询
代码
var filter = Builders<BsonDocument>.Filter.In("Item", new[] { "journal", "notebook" }); var result = collection.Find(filter).ToList();
结果
6.2.6 Not In 查询
代码
var filter = Builders<BsonDocument>.Filter.Nin("Item", new[] { "journal", "notebook" }); var result = collection.Find(filter).ToList();
结果
6.2.7 分页查询
代码
//Skip跳过多少页 Limit 获取多少页 var result = collection.Find(Builders<BsonDocument>.Filter.Empty).Skip(1).Limit(1).ToList();
结果
6.2.8 查询总记录数
代码
var result = collection.Find(Builders<BsonDocument>.Filter.Empty).Count();
结果
6.2.9 查询指定属性
代码
ProjectionDefinition<BsonDocument> projection = Builders<BsonDocument>.Projection.Include("Item").Exclude("_id"); var result = collection.Find(Builders<BsonDocument>.Filter.Empty).Project(projection).ToList();
结果
6.3 嵌套查询
6.3.1 条件为嵌套文档字段时加“.”
代码
var filter = Builders<BsonDocument>.Filter.Eq("Instock.WareHouse", "B"); var result = collection.Find(filter).ToList();
结果
6.3.2 嵌套文档数组元素与指定条件匹配的所有文档
顺序必须一致
代码
var filter = Builders<BsonDocument>.Filter.AnyEq("Instock", new ArrayDocument { WareHouse="A" ,Qty="5" }); var result = collection.Find(filter).ToList();
结果
6.3.3 嵌套文档数组中符合其中一个条件的查询
代码
var filter = Builders<BsonDocument>.Filter.Gt("Instock.0.Qty", 15); var result = collection.Find(filter).ToList();
结果
6.3.4 指定嵌套文档数组索引的元素条件
代码
var filter = Builders<BsonDocument>.Filter.Gt("Instock.0.Qty", 15); var result = collection.Find(filter).ToList();
结果同上
6.3.5 $ElemMatch查询
嵌套文档数组中至少有一个满足条件
代码
//创建过滤器生成器对象 FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter; //创建过滤器 FilterDefinition<BsonDocument> filter = filterBuilder.ElemMatch<BsonDocument>("instock", new ArrayDocument{ Qty = "5", WareHouse = "A" });
6.3.6 不使用ElemMatch的多条件查询, 只要文档数组中满足即可
代码
//创建过滤器生成器对象 FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter; //创建过滤器 FilterDefinition<BsonDocument> filter = filterBuilder.And(filterBuilder.Eq("Instock.Qty",5),filterBuilder.Eq("Instock.WareHouse", "A")); var result = collection.Find(filter).ToList();
6.3.7 查询嵌套文档中符合要求的嵌套文档数据
使用BsonDocument (奇葩使用)
ProjectionDefinition<BsonDocument> projection = Builders<BsonDocument>.Projection.Include("instock").Exclude("_id"); //unwind 展开数组 AppendStage 添加聚合条件 var result = coll.Aggregate().Unwind("instock").AppendStage<BsonDocument>(new BsonDocument { { "$match", new BsonDocument("instock.qty", new BsonDocument("$gt", 30)) } } ).Project(projection).ToList();
使用强模型 mongo会将decimal类型变成字符串存储 ,所以不可使用decimal类型
准备数据
IList<User> users = new List<User> { new User { ID = "1", Name = "狗娃", Age = 11, Order = new List<Order> { new Order{Name="订单1",Price=111}, new Order{Name="订单2",Price=222}, new Order{Name="订单3",Price=333}, } }, new User { ID = "2", Name = "铁蛋", Age = 11, Order = new List<Order> { new Order{Name="订单4",Price=666}, new Order{Name="订单5",Price=454}, new Order{Name="订单6",Price=87}, } }, new User { ID = "3", Name = "狗剩", Age = 11, Order = new List<Order> { new Order{Name="订单7",Price=1}, new Order{Name="订单8",Price=345}, new Order{Name="订单9",Price=653}, } } }; //selectMany 展开子文档数组 var res = coll.AsQueryable().SelectMany(y => y.Order).Where(y=>y.Price>555).ToList();
6.4 查询NULL值属性
6.4.1 数据表
var documents = new[] { new BsonDocument { { "_id", 1 }, { "item", BsonNull.Value } }, new BsonDocument { { "_id", 2 } } }; var documents = new[] { new BsonDocument { Item = null }, new BsonDocument { } }; collection.InsertMany(documents);
6.4.2 查询值为null或者不存在的数据
代码
var filter = Builders<BsonDocument>.Filter.Eq("Item", BsonNull.Value); var result = collection.Find(filter).ToList();
6.4.3 查询值为null的数据
代码
var filter = Builders<BsonDocument>.Filter.Where(u=>u.Item==null);
var result = collection.Find(filter).ToList();
结果
6.4.4 存在检查/查询不存在/存在此属性的值
代码
var filter = Builders<BsonDocument>.Filter.Exists("Item",false); var result = collection.Find(filter).ToList();