MongoDB驱动之Linq操作
添加下面命名空间到您的程序中:
using MongoDB.Driver.Linq;
声明一变量保存对集合的引用
var collection = database.GetCollection<TDocument>("collectionname");
最基本调用linq查询的方式是构造一个集合变量,通过调用AsQueryable<TDocument>() 后,你便可以正常调用linq了。
var query = from e in collection.AsQueryable<Employee>() where e.FirstName == "John" select e; foreach (var employee in query) { // do something }
当然,你也可以通过lambda语法写查询表达式,先前的查询语句等同于下面的写法:
var query = collection.AsQueryable<Employee>().Where(e => e.FirstName == "John");
C#编译器会在内部把所有查询翻译为lambda句法,所以这两种写法没有优略之分,当你需要的时候(比如某些查询操作符不被支持的时候),你甚至可以混用这两种方式。
只有linq查询可以转化为相应的MongoDB查询时该查询才会被支持解析,如果你写的linq查询不能被转化成相应的MongoDB查询,那么您的程序会在产生异常或者错误。
MongoDB支持的LINQ查询操作符
- Any不含谓词的Any只是测试集合中是否存在any文档对象
不含谓词的Any只是测试集合中是否存在any文档对象
var result = (from c in collection.AsQueryable<C>() select c) .Any(); // 或者 var result = collection.AsQueryable<C>() .Any();
- Any (含谓词)
含有谓词的Any用来测试集合中是否存在匹配的文档,匹配逻辑在谓词中
var result = (from c in collection.AsQueryable<C>() select c) .Any(c => c.X == 1); // or var result = collection.AsQueryable<C>() .Any(c => c.X == 1);
投影操作后,带有谓词的Any是不被支持的(至少当前版本),所以下面代码是不可用的。
var result = collection.AsQueryable<C>() .Select(c => c.X) .Any(x => x == 1);
通常来说,你可以使用where字句来替代投影操作,这样你可以移除投影操作。
- Count
不带谓词的Count只是返回文档对象在集合中数量。
var result = (from c in collection.AsQueryable<C>() select c) .Count(); // 或者 var result = collection.AsQueryable<C>() .Count();
- Count (带谓词)
带有谓词的Count返回谓词匹配的文档数量。
var result = (from c in collection.AsQueryable<C>() select c) .Count(c => c.X == 1); // or var result = collection.AsQueryable<C>() .Count(c => c.X == 1);
说明:谓词同样可以通过where字句和不带谓词的Count替代,所以上面实例也可以这样写:
var result = (from c in collection.AsQueryable<C>() where c.X == 1 select c) .Count(); // or var result = collection.AsQueryable<C>() .Where(c => c.X == 1) .Count();
含有谓词的Count同样不支持投影后操作,所以下面写法是无效的。
var result = collection.AsQueryable<C>() .Select(c => c.X) .Count(x => x == 1);
解决方案和Any一样。
- Distinct
Distinct 返回集合中文档对象字段或者属性的唯一值,你可以投影后通过它过滤重复值。
var result = (from c in collection.AsQueryable<C>() select c.X) .Distinct(); // or var result = collection.AsQueryable<C>() .Select(c => c.X) .Distinct();
投影必须选择一个特定的字段或属性的文件。如果该字段或属性的值是在MongoDB中表示,作为一个数组,你也可以使用数组索引从数据中选择一项:
var result = (from c in collection.AsQueryable<C>() select c.A[i]) .Distinct(); // or var result = collection.AsQueryable<C>() .Select(c => c.A[i]) .Distinct();
- ElementAt
ElementAt 从结果集中返回一个特定的文档,通常要和排序操作一起使用
var result = (from c in collection.AsQueryable<C>() where c.X > 0 orderby c.X select c) .ElementAt(index); // or var result = collection.AsQueryable<C>() .Where(c => c.X > 0) .OrderBy(c => c.X) .ElementAt(index);
如果结果集中文档对象数量少于ElementAt 中索引,会报出异常。
- ElementAtOrDefault
ElementAtOrDefault 和ElementAt 类似,区别在于当集合中对象少于Index时前者返回null而不是报出异常。
- First
First 返回集合中第一个对象,通常和排序一起使用。
var result = (from c in collection.AsQueryable<C>() where c.X > 0 orderby c.X select c) .First(); // or var result = collection.AsQueryable<C>() .Where(c => c.X > 0) .OrderBy(c => c.X) .First();
如果集合为空,则First抛出异常
- First (含谓词)
此重载允许你提供谓词逻辑给First,相当于使用where字句的first查询。
var result = (from c in collection.AsQueryable<C>() orderby c.X select c) .First(c => c.X > 0); // or var result = collection.AsQueryable<C>() .OrderBy(c => c.X) .First(c => c.X > 0);
First (含有谓词)同样不支持投影后操作,所以下面代码是无效的:
var result = collection.AsQueryable<C>() .OrderBy(c => c.X) .Select(c => c.X) .First(x => x > 0);
解决方案同样和Any一样
如果集合为空,同样会抛出异常
- FirstOrDefault
FirstOrDefault 和First 不同之处在于,当集合为空时,不会抛出异常,而是返回null
- FirstOrDefault (含谓词)
FirstOrDefault (含谓词)和First(含谓词)用法一样,不同之处在于,集合为空时,返回null不会抛出异常
- Last
Last 从结果集中返回最后一个文档对象,和First相对,通常和排序操作一起使用:
var result = (from c in collection.AsQueryable<C>() where c.X > 0 orderby c.X select c) .Last(); // or var result = collection.AsQueryable<C>() .Where(c => c.X > 0) .OrderBy(c => c.X) .Last();
如果集合为空,会抛出异常。
- Last (含谓词)
此重载允许你传递谓词逻辑作为参数给Last,和不带谓词的Last操作加上where字句相当。
var result = (from c in collection.AsQueryable<C>() orderby c.X select c) .Last(c => c.X > 0); // or var result = collection.AsQueryable<C>() .OrderBy(c => c.X) .Last(c => c.X > 0);
Last 同样不支持投影后操作,所以下面写法是无效的:
var result = collection.AsQueryable<C>() .OrderBy(c => c.X) .Select(c => c.X) .Last(x => x > 0);
解决方案和Any一样。
如果集合为空,会抛出异常
- LastOrDefault
LastOrDefault 和 Last 不同之处在于,前者当集合为空时不会抛出异常,只是返回null
- LastOrDefault (含谓词)
LastOrDefault(含谓词)和 Last (含谓词)用法一样,不同之处在于前者在集合为空时返回null,不会抛出异常。
- LongCount
LongCount 用法和Count 一样,不同之处在于返回值前者是64位长整型,后者是32位。
- LongCount (含谓词)
LongCount (含谓词)和Count (含谓词)用法一样,不同之处在于返回值前者是64位长整型,后者是32位。
- Max
Max 返回集合中文档对象属性或者字段值中的最大值,你可以筛选出投影操作识别出的字段或者属性的最大值
var result = (from c in collection.AsQueryable<C>() select c.X) .Max(); // or var result = collection.AsQueryable<C>() .Select(c => c.X) .Max();
投影必须选择一个特定的字段或属性的文件。如果该字段或属性的值是在MongoDB中表示,作为一个数组,你也可以使用数组索引从数据中选择一项:
var result = (from c in collection.AsQueryable<C>() select c.A[i]) .Max(); // or var result = collection.AsQueryable<C>() .Select(c => c.A[i]) .Max();
- Max (含选择器)
此Max 重载可以让你直接传递选择参数到Max来筛选最大值,可以用来代替在投影后进行Max操作:
var result = (from c in collection.AsQueryable<C>() select c) .Max(c => c.X); // or var result = collection.AsQueryable<C>() .Max(c => c.X);
- Min
Min 返回集合中文档对象属性或者字段值中的最小值,你可以筛选出投影操作识别出的字段或者属性的最小值
var result = (from c in collection.AsQueryable<C>() select c.X) .Min(); // or var result = collection.AsQueryable<C>() .Select(c => c.X) .Min();
投影必须选择一个特定的字段或属性的文件。如果该字段或属性的值是在MongoDB中表示,作为一个数组,你也可以使用数组索引从数据中选择一项:
var result = (from c in collection.AsQueryable<C>() select c.A[i]) .Min(); // or var result = collection.AsQueryable<C>() .Select(c => c.A[i]) .Min();
- Min (含选择器)
此Min 重载可以让你直接传递选择参数到Min来筛选最小值,可以用来代替在投影后进行Min操作:
var result = (from c in collection.AsQueryable<C>() select c) .Min(c => c.X); // or var result = collection.AsQueryable<C>() .Min(c => c.X);
- OfType
OfType操作符会向查询插入一个鉴别器以便你更精确的查询文档对象
var result = (from c in collection.AsQueryable<C>().OfType<D>() select c) // or var result = collection.AsQueryable<C>() .OfType<D>();
- OrderBy
OrderBy 用于指定结果集升序排序顺序
var query = from c in collection.AsQueryable<C>() orderby c.X select c; // or var query = collection.AsQueryable<C>() .OrderBy(c => c.X);
- OrderByDescending
OrderByDescending 用于指定结果集降序排序顺序
var query = from c in collection.AsQueryable<C>() orderby c.X descending select c; // or var query = collection.AsQueryable<C>() .OrderByDescending(c => c.X);
- Select
Select 用于从匹配文档中选出一个新类型的结果集。Select 必须为最后一个操作(除了如 Distinct, Max 和 Min等)
注意:Select 不会减少从服务器返回的文档对象字段或者属性,完整的文档对象还是会被返回的,然后才调用Select 方法,因此投影是在“客户端”的。
var query = from c in collection.AsQueryable<C>() select new { c.X, c.Y }; // or var query = collection.AsQueryable<C>() .Select(c => new { c.X, c.Y });
- Single
Single 从结果集中返回第一个也是唯一的文件
var result = (from c in collection.AsQueryable<C>() where c.X > 0 orderby c.X select c) .Single(); // or var result = collection.AsQueryable<C>() .Where(c => c.X > 0) .OrderBy(c => c.X) .Single();
如果结果集为空或者存在多个文档,Single 会抛出异常。
- Single (含谓词)
此重载可以传递参数到Single ,等同于不含谓词的Single 加上where字句。
var result = (from c in collection.AsQueryable<C>() orderby c.X select c) .Single(c => c.X > 0); // or var result = collection.AsQueryable<C>() .OrderBy(c => c.X) .Single(c => c.X > 0);
Single 同样不支持投影后操作,所以下面代码是无效的:
var result = collection.AsQueryable<C>() .OrderBy(c => c.X) .Select(c => c.X) .Single(x => x > 0);
解决方案和Any一样。
如果结果集为空或者存在多个文档,Single 会抛出异常
- SingleOrDefault
SingleOrDefault 和Single 用法一样,不同之处在于当集合为空或者存在多个文档对象时,会返回null,而不是抛出异常。
- SingleOrDefault (含谓词)
SingleOrDefault(含谓词) 和Single (含谓词)用法一样,不同之处在于当集合为空或者存在多个文档对象时,会返回null,而不是抛出异常。
- Skip
使用Skip ,指定从结果集开始跳过多少文件。通常情况下,你将结合排序操作使用。
var query = (from c in collection.AsQueryable<C>() orderby c.X select c) .Skip(100); // or var query = collection.AsQueryable<C>() .OrderBy(c => c.X) .Skip(100);
- Take
使用Take 指定多少文件从服务器返回。结合Skip 使用时,往往你会指定一个排序顺序。
var query = (from c in collection.AsQueryable<C>() orderby c.X select c) .Skip(100) .Take(100); // or var query = collection.AsQueryable<C>() .OrderBy(c => c.X) .Skip(100) .Take(100);
- ThenBy
ThenBy 是用来指定一个额外的升序排序的结果集。
var query = from c in collection.AsQueryable<C>() orderby c.X, c.Y select c; // or var query = collection.AsQueryable<C>() .OrderBy(c => c.X) .ThenBy(c => c.Y);
- ThenByDescending
ThenByDescending 是用来指定一个额外的降序排序的结果集。
var query = from c in collection.AsQueryable<C>() orderby c.X, c.Y descending select c; // or var query = collection.AsQueryable<C>() .OrderBy(c => c.X) .ThenByDescending(c => c.Y);
- Where
WHERE子句用于指定返回满足条件查询结果。 WHERE子句是将表达查询文档类型映射到一个布尔值句法。如果表达式返回true则结果匹配到结果集中。
var query = from c in collection.AsQueryable<C>() where c.X > 0 select c; // or var query = collection.AsQueryable<C>() .Where(c => c.X > 0);
有时也可以使用多个where字句,其左右相当于&&操作符
例如,下面的查询是等价的:
var query = (from c in collection.AsQueryable<C>() where c.X > 0 where c.Y > 0) .First(c.Z > 0); // or var query = (from c in collection.AsQueryable<C>() where c.X > 0 && c.Y > 0 && c.Z > 0) .First();
- EndsWith
此方法用于测试文档对象的字符串类型的字段或者属性是否以某一个特定的字串结束
var query = from c in collection.AsQueryable<C>() where c.S.EndsWith("abc") select c; // or var query = collection.AsQueryable<C>() .Where(c => c.S.EndsWith("abc"));
//可转化为下面mongodb查询语句(使用了正则表达式): { S : /abc$/ }
- enum 比较 (==, !=, <, <=, >, >=)
枚举字段或者属性可以和同一种类型的枚举常量比较,其真正的比较是基于其底层整数的比较。
public enum E { None, A, B }; var query = from c in collection.AsQueryable<C>() where c.E == E.A select c; // or var query = collection.AsQueryable<C>() .Where(c => c.E == E.A);
//可转化为下面mongodb查询语句 { E : 1 }
//LINQ的实现需要考虑序列化后值得表示方式,所以如果你配置了映射类通过字符串而不是整数来存储枚举值,那么将产生下面的MongoDB查询语句: { E : "A" }
- GetType (返回Type)
这个方法很像OfType方法,会创建一个鉴别器对结果进行更近一步筛选
var query = from c in collection.AsQueryable<C>() where c.GetType() == typeof(D) select c; // or var query = collection.AsQueryable<C>() .Where(c => c.GetType() == typeof(D));
//可大致转化为下面mongodb查询语句(取决于你创建鉴别器的方式) { _t : "D" }
- In (LINQ to MongoDB 扩展方法)
这个方法用于测试一个字段或者属性是否等于提供的一组值中的任何一个。
var query = from c in collection.AsQueryable<C>() where c.X.In(new [] { 1, 2, 3 }) select c; // or var query = collection.AsQueryable<C>() .Where(c.X.In(new [] { 1, 2, 3 }));
//可转化为下面mongodb查询语句: { X : { $in : [1, 2, 3] } }
- Inject
该方法是一个“伪方法”,用于把一个MongoDB查询注入到LINQ中,下面的查询查找大于0的64位整数。
var query = from c in collection.AsQueryable<C>() where c.X > 0 && Query.Type("X", BsonType.Int64).Inject() select c; // or var query = collection.AsQueryable<C>() .Where(c => c.X > 0 && Query.Type("X", BsonType.Int64).Inject());
//可转化为下面mongodb查询语句: { X : { $gt : 0, $type : 18 } }
//is C#关键字 和GetType方法一样
var query = from c in collection.AsQueryable<C>() where c is D && ((D)c).B == 1 select c; // or var query = collection.AsQueryable<C>() .Where(c => c is D && ((D)c).B == 1);
可大致转化为下面mongodb查询语句(取决于你创建鉴别器的方式)
{ _t : "D", B : 1 }
- IsMatch (正则表达式方法)
这个方法用于测试字符串类型的字段或者属性是否匹配一个正则表达式。
var regex = new Regex("^abc"); var query = from c in collection.AsQueryable<C>() where regex.IsMatch(c.S) select c; // or var query = collection.AsQueryable<C>() .Where(c => regex.IsMatch(c.S));
//可转化为下面mongodb查询语句: { S : /^abc/ }
//也可以使用静态IsMatch方法: var query = from c in collection.AsQueryable<C>() where Regex.IsMatch(c.S, "^abc") select c; // or var query = collection.AsQueryable<C>() .Where(c => Regex.IsMatch(c.S, "^abc"));
//可转化为下面mongodb查询语句: { S : /^abc/ }
- Length (数组集合长度)
这个方法用于测试数组集合类型的字段或者属性是否存在一个特定数量的项。
var query = from c in collection.AsQueryable<C>() where c.A.Length == 3 select c; // or var query = collection.AsQueryable<C>() .Where(c => c.A.Length == 3);
//可转化为下面mongodb查询语句: { A : { $size: 3 } }
- % (Mod运算符)
这个方法用于对文档属性或者字段进行求余运算,下面查询匹配所有x属性为偶数的文档
var query = from c in collection.AsQueryable<C>() where c.X % 2 == 1 select c; // or var query = collection.AsQueryable<C>() .Where(c => c.X % 2 == 1);
//可转化为下面mongodb查询语句: { X : { $mod : [2, 1] } }
- ! (Not 操作符)
此方法用于对测试结果进行逻辑非操作
var query = from c in collection.AsQueryable<C>() where !(c.X > 1) select c; // or var query = collection.AsQueryable<C>() .Where(c => !(c.X > 1));
//可转化为下面mongodb查询语句: { X : { $not : { $gt : 1 } } }
注意:
在c.X缺失或者不是数值类型时,!(c.X > 1)不等同于 (c.X <= 1)
数值比较 (==, !=, <, <=, >, >=)
数值类型的字段或者属性可以使用上述任何一种比较方式
var query = from c in collection.AsQueryable<C>() where c.X == 0 && c.Y < 100 select c; // or var query = collection.AsQueryable<C>() .Where(c => c.X == 0 && c.Y < 100);
//可转化为下面mongodb查询语句: { X : 0, Y : { $lt : 100 } }
- || (Or 运算符)
逻辑或运算,进行或比较
var query = from c in collection.AsQueryable<C>() where c.X > 0 || c.Y > 0 select c; // or var query = collection.AsQueryable<C>() .Where(c => c.X > 0 || c.Y > 0);
//可转化为下面mongodb查询语句: { $or : [{ X : { $gt : 0 } }, { Y : { $gt : 0 } }] }
- StartsWith
这个方法用于测试文档对象的字符串字段或者属性是否以某个特定的子串开始
var query = from c in collection.AsQueryable<C>() where c.S.StartsWith("abc") select c; // or var query = collection.AsQueryable<C>() .Where(c => c.S.StartsWith("abc"));
//可转化为下面mongodb查询语句: (可用正则表达式): { S : /^abc/ }
- ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant这些方法用于使文档对象的字符串字段或者属性转为相应的大小写模式
var query = from c in collection.AsQueryable<C>() where c.S.ToLower() == "abc" select c; // or var query = collection.AsQueryable<C>() .Where(c => c.S.ToLower() == "abc");
//可转化为下面mongodb查询语句: (可用正则表达式): { S : /^abc$/i }
此随笔或为自己所写、或为转载于网络。仅用于个人收集及备忘。