2016-06-09 2 views
4

Как я могу преобразовать этот скрипт Mongo Shell в MongoDB C# Driver?MongoDB aggregation Shell script to MongoC# Драйвер

var myItems = [] 

var myCursor = db.Tickets.aggregate(
    [ 
     { $match : { TicketProjectID : 49 } }, 
     { $project: { TicketProjectID:1, TicketID:1, concatValue: { $concat: [ "$Status", " - ", "$Name" ] } } } 
    // I will have a list of fields that I need to concatenate at run time. So C# query should support concatenation for "N" number of fields at run-time. 
     //{ $group: { _id: null, count: { $sum: 1 } } } 

    ], 
     { allowDiskUse: true } 
) 

    //This seems like a ugly performance approach when we are working against 100k results with above match 
    while (myCursor.hasNext()) { 
     var item = myCursor.next(); 
     if(item.concatValue.search(/mysearchkey/i) > -1) 
      { 
       myItems.push(item.TicketID) 
      } 
    }  
    myItems 

или есть лучший способ сделать строку поиска в каскадной проекции вместо Еогеасп в курсоре, так как некоторые п.л. может получить 50k записи.

Это то, что я пытался до сих пор, (не используя Aggregation)

Примечание: подстриженные этот код номера для общественности Q & сайтов A. Поэтому, пожалуйста, рассмотреть это как псевдо-код

var tickets = ticketsCollection.FindSync(filter).ToList(); 
       string concatinatedValue = string.Empty; 
       foreach (var ticket in tickets) 
       { 
        foreach (var field in customFieldsForThisProject) 
         concatinatedValue += ticket[field.Replace(" ", "_")]; 

        if(concatinatedValue.StripHtml().contains("MysearchWord")) 
       { 
        TikectIdList.Add(ticket["TicketID"]) 
       } 
       } 
+0

@KDecker обновленный вопрос с тем, что я пробовал. Я не пытался использовать Aggregation с C# Driver. – HaBo

ответ

2

Отредактировано в соответствии с данным комментарием

Если вы можете использовать AsQueryable() вы можете получить значения, как это:

var dbResult = from ticket in ticketsCollection.AsQueryable() 
       where ticket.TicketProjectID == 49 
       select new 
       { 
        TicketProjectID = ticket.TicketProjectID, 
        TicketID = ticket.TicketID, 
        ConcatValue = ticket.Status + " - " + ticket.Name 
       }; 

и чем позже вы можете сделать что-то вроде этого:

var result = from dbr in dbResult 
      where dbr.ConcatValue.Contains("something") //or 
      where dbr.ConcatValue.StartsWith("something")//or you can use regex 
      select dbr; 

Примечание: По некоторым причинам оба Status и Name свойства от типа Ticket должно быть типа String для конкатенации, чтобы работать, так как водитель Монго не распознает вызов ToString() из некоторых другого типа.

Если вы хотите объединить свойства некоторых других типов, вы можете получить их отдельно от db и конкатенировать их локально.

note, i'm not that good with mongo shell i could mess something up but you can see in which way you could go

В качестве альтернативы вы можете написать команду оболочки, как это и поместить его в строку:

var command = @"db.Tickets.aggregate(
[ 
    { $project: { TicketProjectID:1, TicketID:1, concatValue: { $concat: [ "$Status", " - ", "$Name" ] } } }, 
    { $match : { TicketProjectId : 49, concatValue : { $regex : /mysearchkey/i } } } 
], 
{ allowDiskUse : true } 
);"; 

затем выполнить его в C# с RunCommandAsync методом из MongoDatabase.

var result = await mongoDatabase.RunCommandAsync<BsonDocument>(BsonDocument.Parse(command)); 
+0

TicketProjectID = 1 указывает на включение этого поля в результат и игнорирование останова. – HaBo

+0

Спасибо за ввод, я отредактировал ответ –

+0

Мне нужна эта динамика, «ticket.Status +» - «+ ticket.Name» У меня будет список полей, которые мне нужны для конкатенации, поэтому как я могу это построить конкатенация во время выполнения? – HaBo

3

Благодаря @ Nikola.Lukovic, работая на его псевдо-код, я пришел с этим рабочим раствором.

подход один: полностью с использованием C# Driver

var ticketsCollection = _mongoConnect.Database.GetCollection<BsonDocument>("Tickets"); 

      var dbResult = from ticket in ticketsCollection.AsQueryable() 
       select new 
       { 
        TicketProjectID = ticket["TicketProjectID"], 
        TicketID = ticket["TicketID"], 
        ConcatValue = ticket["Status"] + (string) ticket["Name"] 
       }; 
      var matches = from dbr in dbResult 
       where dbr.ConcatValue.Contains(searchKey) 
       where dbr.ConcatValue.StartsWith(searchKey) 
       select dbr; 

Это не будет работать для моего сценария, как поля я пытаюсь СЦЕПИТЬ являются ли тип строки, но $add будет работать только с numeric и date.

подход два: с помощью RunCommand и переходя прямо команду Shell. Это будет работать для всех типов данных. И работает и для моей нужды.

 var projectCommand = 
      BsonDocument.Parse(
       "{ $project: { _id: -1, TicketProjectID:1, TicketID:1, concatValue: { $concat: [ \"$Status\", \" - \", \"$Name\" ] } } }"); 
     var matchCommand = 
      BsonDocument.Parse("{ $match: {concatValue: { $regex: '" + searchKey + "', $options: 'i'} } }"); 

     var pipeline = new[] {projectCommand, matchCommand}; 
     var result = ticketsCollection.Aggregate<BsonDocument>(pipeline).ToList(); 
     if (result.Count > 0) 
      return result.Select(x => (int)x["TicketID"]).ToList(); 
     return null;