扩展MongoDB C# Driver的QueryBuilder

由于不想直接hardcode "ClassA.MemberA.MemberB" 这样的字符串 ,写了以下几个类,用于以下常用的场景:
1. 表达式转换成字符串函数: ExpToStr()
2. Collection函数:当有集合成员时,可以使用此类,将返回QueryCollection对象,这个类的代码之后附上
3. CollectionAs函数:当使用了继承,希望将基类转换为子类并返回子类的QueryCollection

使用示例:

//获得表达式的字符串形式
1. QueryEx<ClassA>.ExpToStr ((ClassA m)=> m.MemberA.MemberB.MemberC)

//集合.成员.字段
//PoppedSegments为集合,AssignedNetwork.Name为成员
//将返回PoppedSegments.AssignedNetwork.Name
2. QueryEx<MDDelivery>.Collection(x => x.PoppedSegments).Matches(p => p.AssignedNetwork.Name, bsonRegex),

//子类集合.成员.字段
//STPaymentTransaction为基类,STPaymentCompanyCredit为子类,Company字段在子类中
//将返回Payments.Company.Name
3. QueryEx<MDDelivery>.CollectionAs<STPaymentTransaction, STPaymentCompanyCredit>(x=>x.Payments).Matches(p=>p.Company.Name, bsonRegex)

//集合.集合.成员.字段
//Parcels为集合,STCustomPropertyRuntime为基类,STNumericPropertyRuntime为子类,CustomProps为STNumericPropertyRuntime中成员,Value为CustomProp中成员
//将返回Parcels.CustomProps.Value
4. QueryEx<MDDelivery>.Collection(x=>x.Parcels).CollectionMemberAs<STCustomPropertyRuntime, STNumericPropertyRuntime>(p=>p.CustomProps).Matches(p=>p.Value, bsonRegex),

实现代码:

public class QueryEx<TDocument>
    {
        public static QueryCollection<TDocument, TCollection> Collection<TCollection>(
            Expression<Func<TDocument, IEnumerable<TCollection>>> collectionExpression)
        {
            return new QueryCollection<TDocument, TCollection>(collectionExpression);
        }

        //for those cases using inheritance
        //e.g STPaymentTransaction
        //Payments will return STPaymentTransaction
        //need to cast to sub classes(STPaymentCompanyCredit) so that be able to filter by child members (e.g. Company)
        public static QueryCollection<TDocument, TSub> CollectionAs<TCollection, TSub>(
            Expression<Func<TDocument, IEnumerable<TCollection>>> collectionExpression)
            where TSub : TCollection
        {
            var argParam = Expression.Parameter(typeof (TDocument), "x");
            var memberStr = ExpToStr(collectionExpression);
            MemberExpression nameProperty = Expression.Property(argParam, memberStr);

            var subExp = Expression.Convert(nameProperty, typeof(IEnumerable<TSub>));

            var exp = Expression.Lambda<Func<TDocument, IEnumerable<TSub>>>(
                subExp,
                argParam);

            return new QueryCollection<TDocument, TSub>(exp);
        }

        /// <summary>
        /// return string value for a expression:
        /// for s.Name.Val1.Val2 will return Name.Val1.Val2
        /// </summary>
        /// <typeparam name="MDClass"></typeparam>
        /// <typeparam name="Member"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static string ExpToStr<TDocument, Member>(Expression<Func<TDocument, Member>> exp)
        {
            return new QueryExpressionHelper().MemberExpression(exp);
        }
    }

public class QueryCollection<TDocument, TCollection>
    {
        private readonly QueryExpressionHelper _queryExpression;
        private string _collectionName;

        public string Context
        {
            get { return _collectionName; }
        }

        public QueryCollection(Expression<Func<TDocument, IEnumerable<TCollection>>> collectionExpression)
        {
            _queryExpression = new QueryExpressionHelper();
            _collectionName = _queryExpression.MemberExpression(collectionExpression);
        }

        public QueryMember<TCollection, TMember> Member<TMember>(Expression<Func<TCollection, TMember>> exp)
        {
            var expStr = QueryEx<TCollection>.ExpToStr(exp);
            var context = string.Format("{0}.{1}", _collectionName, expStr);
            var obj = new QueryMember<TCollection, TMember>(context);

            return obj;
        }

        public QueryCollection<TCollection, TMember> CollectionMember<TMember>(
            Expression<Func<TCollection, IEnumerable<TMember>>> exp)
        {
            var expStr = QueryEx<TCollection>.ExpToStr(exp);
            var obj = new QueryCollection<TCollection, TMember>(exp)
            {
                _collectionName = string.Format("{0}.{1}", _collectionName, expStr)
            };

            return obj;
        }

        /// <summary>
        /// this method only support 1 layer nested(not for Query Collection.Collection , but for Collection.Member)
        /// if member is collection and need convert to sub class
        /// </summary>
        /// <typeparam name="TMember">Base Type</typeparam>
        /// <typeparam name="TMemberSub">Child Class Type</typeparam>
        /// <param name="collectionExpression"></param>
        /// <returns></returns>
        public QueryCollection<TCollection, TMemberSub> CollectionMemberAs<TMember, TMemberSub>(
            Expression<Func<TCollection, IEnumerable<TMember>>> collectionExpression)
            where TMemberSub : TMember
        {
            var obj = QueryEx<TCollection>.CollectionAs<TMember, TMemberSub>(collectionExpression);
            obj._collectionName = string.Format("{0}.{1}", _collectionName, obj._collectionName);

            return obj;
        }

        public IMongoQuery LT<TMember>(Expression<Func<TCollection, TMember>> memberExpression, TMember value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.LT(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
        }

        public IMongoQuery LT<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, TValue value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.LT(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
        }

        public IMongoQuery EQ<TMember>(Expression<Func<TCollection, TMember>> memberExpression, TMember value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.EQ(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
        }

        public IMongoQuery EQ<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, TValue value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.EQ(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
        }

        public IMongoQuery NE<TMember>(Expression<Func<TCollection, TMember>> memberExpression, TMember value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.NE(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
        }

        public IMongoQuery NE<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, TValue value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.NE(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
        }

        public IMongoQuery In<TMember>(Expression<Func<TCollection, TMember>> memberExpression, params TMember[] values)
        {
            return In<TMember>(memberExpression, new List<TMember>(values));
        }

        public IMongoQuery In<TMember>(Expression<Func<TCollection, TMember>> memberExpression,
            IEnumerable<TMember> values)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);
            return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
        }

        public IMongoQuery In<TCastC, TMember>(Expression<Func<TCastC, TMember>> memberExpression,
            IEnumerable<TMember> values) where TCastC : TCollection
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);
            return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
        }

        public IMongoQuery In<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, IEnumerable<TValue> values)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);
            return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
        }

        public IMongoQuery In<TCastC, TValue>(Expression<Func<TCastC, IEnumerable<TValue>>> memberExpression, IEnumerable<TValue> values) where TCastC : TCollection
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);
            return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
        }

        public IMongoQuery Matches<TMember>(Expression<Func<TCollection, TMember>> memberExpression, BsonRegularExpression value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.Matches(string.Format("{0}.{1}", _collectionName, memberName), value);
        }

        public IMongoQuery Matches<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, BsonRegularExpression value)
        {
            var memberName = _queryExpression.MemberExpression(memberExpression);

            return Query.Matches(string.Format("{0}.{1}", _collectionName, memberName), value);
        }
    }

public class QueryMember<TDocument, TCollection>
    {
        private readonly QueryExpressionHelper _queryExpression;
        private string _collectionName;

        public string Context
        {
            get { return _collectionName; }
        }

        public QueryMember(Expression<Func<TDocument, TCollection>> exp)
        {
            _queryExpression = new QueryExpressionHelper();
            _collectionName = _queryExpression.MemberExpression(exp);
        }

        public QueryMember(string context)
        {
            _collectionName = context;
        }

    }

public class QueryExpressionHelper
    {
        public string Context;

        public string MemberExpression<TMember>(Expression<TMember> expression)
        {
            MemberExpression me;
            switch (expression.Body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    me = expression.Body as MemberExpression;
                    break;
                case ExpressionType.Convert:
                    dynamic convertedBody = expression.Body;
                    me = convertedBody.Operand as MemberExpression;
                    break;

                default:
                    throw new NotSupportedException(string.Format("Member with node type {0} is not supported. expression {1}", expression.Body.NodeType, expression));
            }
            var stack = new Stack<string>();

            while (me != null)
            {
                stack.Push(me.Member.Name);
                me = me.Expression as MemberExpression;
            }

            var expStr = string.Join(".", stack.ToArray());
            return expStr;

        }
    }

public static class QueryMoney
    {
        public static IMongoQuery Value(string name, double val)
        {
            var accuracy = 0.005;

            return Query.And(
                Query.LT(name, new BsonDouble(val + accuracy)),
                Query.GT(name, new BsonDouble(val - accuracy)));
        }
    }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 23:53:08

扩展MongoDB C# Driver的QueryBuilder的相关文章

mongodb c# driver(驱动)介绍及CURD

mongodb c# driver(驱动)介绍 目前基于C#的mongodb驱动有两种,分别是官方驱动(下载地址)和samus驱动(下载地址). 本次我们只演示官方驱动的使用方法. 官方驱动文档查看 第一步:引用驱动dll 引用驱动有两种方式: 1. 根据上面的下载地址下载对应的版本,然后引用到项目中. 2. 在项目的引用上右击->管理NuGet程序包(首先确保安装了nuget扩展包)->联机搜索官方驱动dll(搜索条件是 “Official MongoDB”)->安装成功后会引用3个d

收录mongodb C# driver 说明

C# driver Releases notes C# driver 指南(博客园友翻译) Mongodb Connection String mongodb的write concern 各版本驱动解决的问题(JIRA) 收录mongodb C# driver 说明,布布扣,bubuko.com

mongodb c++ driver 2.0编译使用

安装boost1.48.0 在boost的官网下载boost1.48.0,链接例如以下: http://sourceforge.net/projects/boost/files/boost/1.48.0/boost_1_48_0.tar.gz/download tar -xzvf boost_1_48_0.tar.gz解压到当前文件夹 cd boost_1_48_0进入boost库文件夹 ./bootstrap.sh在当前文件夹生成bjam可运行程序 ./bjam --layout=versio

MongoDB C driver API continues

开篇前 <1,mongoc_init() func> mongoc_init() Synopsis void mongoc_init (void); Description This function should be called at the beginning of every program using the MongoDB C driver. It is responsible for initializing global state such as process count

[原创]MongoDB C++ 驱动部分问题解决方案(MongoDB C++ Driver)

本文为我长时间开发以及修改MongoDB C++ Driver时的一些问题和解决方案.目前本文所介绍的相关引擎也已经发布闭源版本,请自行下载 库版本以及相关位置:http://code.google.com/p/mongodb-cpp-engine/ Q & A1.C++版本驱动我们需要另行封装么?A:并非一定要做此类行为,不过如果我们增加和使用一个连接池其稳定性将远远优于我们的想想. 2.C++版本的驱动除了官方版本外,还有什么版本么?A:目前未知,但我已经完成了一版线程安全的版本,下载地址:

扩展 MongoDB.Driver 支持实体使用方式

一.安装 Install-Package Apteryx.MongoDB.Driver.Extend 移步我的项目https://github.com/code-institutes/Apteryx.MongoDB.Driver.Extend有详细的使用说明. 原文地址:https://www.cnblogs.com/apteryx/p/10818941.html

centos上的mongodb的安装及php扩展mongodb

mongodb的官网https://www.mongodb.org,可在其上下载你想要的版本.下面是我的下载.安装及启动 curl -O -L https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.4.tgz tar -zxvf mongodb-linux-x86_64-3.0.4.tgz  cd mongodb-linux-x86_64-3.0.4 mkdir -p /usr/local/mongodb ln -s /usr/loc

MongoDB .Net Driver(C#驱动) - 内嵌数组/嵌入文档的操作(增加、删除、修改、查询(Linq 分页))

目录 一.前言 (一) 运行环境 二.前期准备工作 (一) 创建 MongoDBContext MongoDb操作上下文类 (二)创建测试类 (三) 创建测试代码 三.内嵌数组增加元素操作 (一) Update.Set()方法 替换内嵌数组(不推荐使用) (二)Update.Push()方法 直接将元素压入内嵌数组(推荐) (三) Update.PushEach()方法 将多个元素压入内嵌数组(推荐) 四.内嵌数组删除元素操作 (一) Update.Set()方法 替换内嵌数组(不推荐使用) (

windows下使用Cmake和VC 2013安装mongodb C driver

Windows下安装mongodb的C语言程序驱动必须借助交叉编译软件CMake,但是官网上的文档对于一些细节交代的非常不清楚,昨天弄了半天,总算成功安装了,步骤如下: 1.下载mongodb 将mongo-c-driver-1.1.4.zip源代码解压到d:根目录下(此目录路径可根据需要选定). 2.下载libbson库,https://github.com/mongodb/libbson/releases/download/1.1.6/libbson-1.1.6.tar.gz,将其解压.将解