2012-07-26 106 views
1

*蒙戈新手在這裏MongoDB的 - 結合多個數字範圍查詢(C#驅動程序)

我有一個包含幾百個數字領域,我需要在組合查詢的文檔。

var collection = _myDB.GetCollection<MyDocument>("collection"); 
IMongoQuery mongoQuery; // = Query.GT("field", value1).LT(value2); 
foreach (MyObject queryObj in Queries) 
{ 
    // I have several hundred fields such as Height, that are in queryObj 
    // how do I build a "boolean" query in C# 
    mongoQuery = Query.GTE("Height", Convert.ToInt16(queryObj.Height * lowerbound)); 
} 

我有幾百個領域,如高度(例如寬度,面積,周長等),是在queryObj我怎麼建立在C#中「布爾」查詢相結合的範圍查詢每個字段結合。

我試圖使用示例Query.GT(「field」,value1).LT(value2);,但編譯器不接受LT(Value)構造。無論如何,我需要通過遍歷每個數字字段值來構建一個複雜的布爾查詢。

感謝您幫助新手出去。

回答

4

編輯3:

好了,它看起來像您現在已經建立了複雜的查詢有代碼。在這種情況下,您只需修復編譯器問題。我假設你要做到以下幾點(x > 20 && x < 40) && (y > 30 && y < 50) ...

var collection = _myDB.GetCollection<MyDocument>("collection"); 
var queries = new List<IMongoQuery>(); 

foreach (MyObject queryObj in Queries) 
{ 
    //I have several hundred fields such as Height, that are in queryObj 
    //how do I build a "boolean" query in C# 

    var lowerBoundQuery = Query.GTE("Height", Convert.ToInt16(queryObj.Height * lowerbound)); 
    var upperBoundQuery = Query.LTE("Height", Convert.ToInt16(queryObj.Height * upperbound)); 

    var query = Query.And(lowerBoundQuery, upperBoundQuery); 
    queries.Add(query); 
} 

var finalQuery = Query.And(queries); 
/* 
    if you want to instead do an OR, 
    var finalQuery = Query.Or(queries); 
*/ 

原來的答覆。

var list = _myDb.GetCollection<MyDoc>("CollectionName") 
       .AsQueryable<MyDoc>() 
       .Where(x => 
         x.Height > 20 && 
         x.Height < 40) 
       .ToList(); 

我曾嘗試使用的示例Query.GT( 「場」,值1).LT(值2);, 但是編譯器不接受LT(值)構建體。

如果您使用官方的C#驅動程序,您可以使用linq查詢MongoDB。這應該解決我認爲的編譯器問題。

我想到的更有趣的問題是,你將如何構造複雜的布爾查詢?

一種選擇是動態建立一個Expression,然後傳遞到Where

我的同事正在使用類似的東西,下面的代碼...

public static IQueryable<T> Where<T>(this IQueryable<T> query, 
     string column, object value, WhereOperation operation) 
    { 
     if (string.IsNullOrEmpty(column)) 
      return query; 

     ParameterExpression parameter = Expression.Parameter(query.ElementType, "p"); 

     MemberExpression memberAccess = null; 
     foreach (var property in column.Split('.')) 
      memberAccess = MemberExpression.Property 
       (memberAccess ?? (parameter as Expression), property); 

     //change param value type 
     //necessary to getting bool from string 
     ConstantExpression filter = Expression.Constant 
      (
       Convert.ChangeType(value, memberAccess.Type) 
      ); 

     //switch operation 
     Expression condition = null; 
     LambdaExpression lambda = null; 
     switch (operation) 
     { 
      //equal == 
      case WhereOperation.Equal: 
       condition = Expression.Equal(memberAccess, filter); 
       lambda = Expression.Lambda(condition, parameter); 
       break; 
      //not equal != 
      case WhereOperation.NotEqual: 
       condition = Expression.NotEqual(memberAccess, filter); 
       lambda = Expression.Lambda(condition, parameter); 
       break; 
      //string.Contains() 
      case WhereOperation.Contains: 
       condition = Expression.Call(memberAccess, 
        typeof(string).GetMethod("Contains"), 
        Expression.Constant(value)); 
       lambda = Expression.Lambda(condition, parameter); 
       break; 
     } 


     MethodCallExpression result = Expression.Call(
       typeof(Queryable), "Where", 
       new[] { query.ElementType }, 
       query.Expression, 
       lambda); 

     return query.Provider.CreateQuery<T>(result); 
    } 

public enum WhereOperation 
{ 
    Equal, 
    NotEqual, 
    Contains 
} 

目前,它僅支持== & & !=,但它應該不是那麼難實施>=<= ...

你可以從表達式類得到一些提示:http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

編輯:

var props = ["Height", "Weight", "Age"]; 
var query = _myDb.GetCollection<MyDoc>("CName").AsQueryable<MyDoc>(); 
foreach (var prop in props) 
{ 
    query = query.Where(prop, GetLowerLimit(queryObj, prop), WhereOperation.Between, GetUpperLimit(queryObj, prop)); 
} 
// the above query when iterated over, will result in a where clause that joins each individual `prop\condition` with an `AND`. 
// The code above will not compile. The `Where` function I wrote doesnt accept 4 parameters. You will need to implement the logic for that yourself. Though it ought to be straight forward I think... 

編輯2:

如果你不想使用LINQ,你仍然可以使用Mongo查詢。您只需要使用Query.And()Query.Or()來製作您的查詢。

 // I think this might be deprecated. Please refer the release notes for the C# driver version 1.5.0 
     Query.And(Query.GTE("Salary", new BsonDouble(20)), Query.LTE("Salary", new BsonDouble(40)), Query.GTE("Height", new BsonDouble(20)), Query.LTE("Height", new BsonDouble(40))) 

     // strongly typed version 
     new QueryBuilder<Employee>().And(Query<Employee>.GTE(x => x.Salary, 40), Query<Employee>.LTE(x => x.Salary, 60), Query<Employee>.GTE(x => x.HourlyRateToClients, 40), Query<Employee>.LTE(x => x.HourlyRateToClients, 60)) 
+0

嗨,感謝您的回覆,但我如何建立一個範圍列表例如Where(x => x.Height> 20 && x.Height < 40), y => y.Height> 30 && y.Height <60)等等。 – Mikos 2012-07-26 11:51:01

+0

最好是否有非LINQ方式?或者是LINQ我唯一的選擇? – Mikos 2012-07-26 11:53:21

+0

編輯是否有幫助? .. Cuz,老實說,我不明白你在評論中寫的「Where」的例子。它不會編譯。 'Where'不接受'x'和'y'兩個參數... – 2012-07-26 12:07:01

相關問題