.net下samus Mongo-Cshap 引擎中的find原生查询
一(问题)
在实现web前台把筛选条件提交到查询时。我们遇到了一些不大不小难题:

这是一个复杂的选择。而后台可接受的查询格式最终决定前台在提交的数据格式,根据目前所知的。mongoDb的samus引擎 提供了find,where方法,接受的参数很灵活:lambda/selector/javascript Fun,
而网上提供的资料相当少,对于我们.net一族,最常用的还是lambda表达式,但据说复杂的还是不能完美支持,同时会有一些效率问题。
而我们需要象原生支持的灵活参数,用于我们前台get请求时的url格式设计,这里介绍一下selector的查询方式。高人们可以直接飘过。
二,原理解决
首先我们看看mongo的原生查询(常用)
$gt : >
$lt : <
$gte: >=
$lte: <=
$ne : !=、<>
$in : in
$nin: not in
$all: all
$not: 反匹配(1.3.3及以上版本)
在看看samus引擎的 query operators 类 (Op.cs )
using System;
using MongoDB.Bson;
namespace MongoDB
{
/// <summary>
/// Staticly typed way of using MongoDB query operators.
/// </summary>
public class Op : Document
{
/// <summary>
/// Initializes a new instance of the <see cref="Op"/> class.
/// </summary>
/// <remarks>Only allow instantiation through static methods.</remarks>
private Op()
{ }
/// <summary>
/// Matches an object which is greater than the specified value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static Op GreaterThan<T>(T value)
{
return (Op)new Op().Add("$gt", value);
}
/// <summary>
/// Matches an object which is greater than or equal to the specified value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static Op GreaterThanOrEqual<T>(T value)
{
return (Op)new Op().Add("$gte", value);
}
/// <summary>
/// Matches an object which is less than the specified value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static Op LessThan<T>(T value)
{
return (Op)new Op().Add("$lt", value);
}
/// <summary>
/// Matches an object which is less than or equal to the specified value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static Op LessThanOrEqual<T>(T value)
{
return (Op)new Op().Add("$lte", value);
}
/// <summary>
/// Matches an object which does not equal the specified value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static Op NotEqual<T>(T value)
{
return (Op)new Op().Add("$ne", value);
}
/// <summary>
/// Matches an array which has one of the specified values.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="values">The values.</param>
/// <returns></returns>
public static Op In<T>(params T[] values)
{
return (Op)new Op().Add("$in", values);
}
/// <summary>
/// Matches an array which does not have any of the specified values.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="values">The values.</param>
/// <returns></returns>
public static Op NotIn<T>(params T[] values)
{
return (Op)new Op().Add("$nin", values);
}
/// <summary>
/// Matches an array which has all of the specified values.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="values">The values.</param>
/// <returns></returns>
public static Op All<T>(params T[] values)
{
return (Op)new Op().Add("$all", values);
}
/// <summary>
/// Modulus operator.
/// </summary>
/// <param name="denominator">The denominator.</param>
/// <param name="result">The result.</param>
/// <returns></returns>
public static Op Mod(int denominator, int result)
{
return (Op)new Op().Add("$mod", new[] { denominator, result });
}
/// <summary>
/// Matches any array with the specified number of elements
/// </summary>
/// <param name="size">The size.</param>
/// <returns></returns>
public static Op Size(int size)
{
return (Op)new Op().Add("$size", size);
}
/// <summary>
/// Check for existence of a field.
/// </summary>
/// <returns></returns>
public static Op Exists()
{
return (Op)new Op().Add("$exists", true);
}
/// <summary>
/// Check for lack of existence of a field.
/// </summary>
/// <returns></returns>
public static Op NotExists()
{
return (Op)new Op().Add("$exists", false);
}
/// <summary>
/// Matches values based on their bson type.
/// </summary>
/// <param name="bsonType">Type of the bson.</param>
/// <returns></returns>
public static Op Type(BsonType bsonType)
{
return (Op)new Op().Add("$type", (int)bsonType);
}
/// <summary>
/// Sends the Javascript expressiosn to the server.
/// </summary>
/// <param name="javascript">The javascript.</param>
/// <returns></returns>
public static Op Where(string javascript)
{
if(javascript == null)
throw new ArgumentNullException("javascript");
return (Op)new Op().Add("$where", new Code(javascript));
}
/// <summary>
/// Implements the operator &. This is used for conjunctions.
/// </summary>
/// <param name="op1">The op1.</param>
/// <param name="op2">The op2.</param>
/// <returns>The result of the operator.</returns>
public static Op operator &(Op op1, Op op2)
{
return (Op)new Op().Merge(op1).Merge(op2);
}
/// <summary>
/// Implements the operator !. This is used for the meta operator $not.
/// </summary>
/// <param name="op">The op.</param>
/// <returns>The result of the operator.</returns>
public static Op operator !(Op op)
{
return (Op)new Op().Add("$not", op);
}
}
}
OK!很清楚了,下面是具体用法
//得到collection
IMongoCollection<TEntity> collection= db.GetCollection<TEntity>();
//一般查询
collection.Find(new{name="张三"});
collection.Find(new{name="张三",sex="女"}); //and的关系
//js查询
string jsStr = @"
function(){
return this.name == '张三' || this.name == '李四';
}
";
collection.where(jsStr); //这回可以or了。js查询很强大,支持正则表达式,能解决like查询,请自行发挥
//涉及op的查询
collection.Find((Op.Where(jsStr)); //使用上面的jsFunction
collection.Find(new{age=Op.GreaterThan(18)}); //age>18
collection.Find(new{age=Op.GreaterThan(18).LessThan(30)}); // 30>age>18
collection.Find(new{age=Op.In(18,28,38)}); //age==18 || age==28 || age==38
collection.Find(new{comment=Op.All("高","帅","钱多")}); //不做解释了自己查 $all
三,最终实现
最后定了一个规则,前台get字符串类似于 fieldA:xxxx;fieldB:xxxx 这里的xxxx是正则表达式,后台生成javascript的function字串,然后....
四,疑问
a. javascript 查询,可以有多复杂,其机制是什么? 效率如何?
经试验,只对第一个function有效,不能闭包
浙公网安备 33010602011771号