2015-07-28 4 views
2

В настоящее время я работаю над драйвером Csharp LinQ для MongoDb, и у меня возникают проблемы с внедрением метода, подобного вызову хранимой функции на MongoDb. На самом деле, я знаю, что MongoDB не имеет механизма хранимой процедуры. И мне нужно, чтобы кто-то дал предложение или решение для этого. Важная вещь, которая каким-то образом будет передана в mongodb, не будет выполнена в памяти. Например, я хочу вернуть список с условием фильтрации, который реализуется пользовательским методом. Этот метод вычисляет базу на зависимостях полей.Функция вызова с использованием драйвера Mongodb-CSharp

Пример выполнен в памяти.

var list = collection.AsQueryable<Rule>().ToList();  
var result = list.Where(x => x.Active && CalcMethod(x.Rule)> 5); 

И пользовательский метод здесь.

public static int CalcMethod(Rule rule) 
{   
    if(rule.Active) 
     // bypass check null 
     return rule.Weight.Unit * rule.Weight.Value; 
    else 
     // return something here 
} 

Метод CalcMethod как функция в SQL Server. Можем ли мы сделать это с помощью MongoDb или другого, ожидаем, что мы можем ввести метод для вычисления данных и фильтрации без выполнения в памяти. Каждая помощь будет оценена по достоинству.

+1

Этот тип синтаксиса не очень хорошо работает с MongoDB. Если вы хотите, чтобы результаты вычислялись по полям, тогда посмотрите на [структуру агрегации] (http://docs.mongodb.org/manual/core/aggregation-introduction/). Это обрабатывает больше операций с полем, которые вы делаете с SQL, по сравнению с общей формой запроса «найти». –

+0

Это хорошо, спасибо. Я придерживался повторно используемых методов, это сложные функции, которые не поддерживаются MongoDB, выше - это только базовый метод. Поскольку запросы создаются из пользовательского интерфейса, он будет выглядеть так, как запрос выражения Linq и система позволяют выполнять эти сложные вещи динамически. Использование структуры агрегации - это конвертер потребностей для их преобразования. Если вы знаете что-то подобное, дайте свой совет – cyworld8x

ответ

0

Soner, Я думаю, вы можете использовать для этого агрегацию (или MapReduce для сложных вещей). т.е.:

async void Main() 
{ 

    var client = new MongoClient("mongodb://localhost"); 
    var db = client.GetDatabase("TestSPLike"); 
    var col = db.GetCollection<Rule>("rules"); 

    await client.DropDatabaseAsync("TestSPLike"); // recreate if exists 
    await InsertSampleData(col); // save some sample data 

    var data = await col.Find(new BsonDocument()).ToListAsync(); 
    //data.Dump("All - initial"); 

/* 
    db.rules.aggregate(
    [ 
    { $match: 
     { 
     "Active":true 
     } 
    }, 
    { $project: 
     { 
     Name: 1, 
     Active: 1, 
     Weight:1, 
     Produce: { $multiply: [ "$Weight.Unit", "$Weight.Value" ] } 
     } 
    }, 
    { $match: 
     { 
      Produce: {"$gt":5} 
     } 
    } 
    ] 
) 
*/ 

var aggregate = col.Aggregate() 
    .Match(new BsonDocument{ {"Active", true} }) 
    .Project(new BsonDocument { 
     {"Name", 1}, 
     {"Active", 1}, 
     {"Weight",1}, 
     {"Produce", 
     new BsonDocument{ 
      { "$multiply", new BsonArray{"$Weight.Unit", "$Weight.Value"} } 
     }} 
    }) 
    .Match(new BsonDocument { 
     { "Produce", 
      new BsonDocument{ {"$gt",5} } 
      } 
      }) 
    .Project(new BsonDocument { 
     {"Name", 1}, 
     {"Active", 1}, 
     {"Weight",1} 
     }); 
    var result = await aggregate.ToListAsync(); 
    //result.Dump(); 
} 

private async Task InsertSampleData(IMongoCollection<Rule> col) 
{ 
var data = new List<Rule>() { 
    new Rule { Name="Rule1", Active = true, Weight = new Weight { Unit=1, Value=10} }, 
    new Rule { Name="Rule2", Active = false, Weight = new Weight { Unit=2, Value=3} }, 
    new Rule { Name="Rule3", Active = true, Weight = new Weight { Unit=1, Value=4} }, 
    new Rule { Name="Rule4", Active = true, Weight = new Weight { Unit=2, Value=2} }, 
    new Rule { Name="Rule5", Active = false, Weight = new Weight { Unit=1, Value=5} }, 
    new Rule { Name="Rule6", Active = true, Weight = new Weight { Unit=2, Value=4} }, 
}; 

await col.InsertManyAsync(data,new InsertManyOptions{ IsOrdered=true}); 
} 

public class Weight 
{ 
    public int Unit { get; set; } 
    public int Value { get; set; } 
} 

public class Rule 
{ 
    public ObjectId _id { get; set; } 
    public string Name { get; set; } 
    public bool Active { get; set; } 
    public Weight Weight { get; set; } 
}