2016-11-29 55 views
1

我有一个包含集合的数据库,包含窗体上的文档这些集合查找场最大值:在所有集合

{ "_id" : 4, "value" : 2 } 

我想找到的最大"_id"在一个有效的方式,所有的藏品。目前,我有一个工作方法:

public long getLastTimestamp() 
{ 
    var tempList = getChannelNames(); 
    var channelList = new List<IMongoCollection<BsonDocument>>(); 
    var docuList = new List<BsonDocument>(); 

    foreach (var channel in tempList) 
    { 
     channelList.Add(_database.GetCollection<BsonDocument>(channel.name)); 
    } 

    foreach (var channel in channelList) 
    { 
     var filter = Builders<BsonDocument>.Filter.Exists("_id"); 
     var result = channel.FindAsync(filter).Result.ToList(); 

     foreach (var docu in result) 
     { 
      docuList.Add(docu); 
     } 
    } 

    var timeList = new List<long>(); 

    foreach (var docu in docuList) 
    { 
     Console.WriteLine(docu); 
     if (!docu["_id"].IsObjectId) 
      timeList.Add(docu["_id"].ToInt64()); 
    } 

    return timeList.Max(); 
} 

它的工作原理,但我不认为它是非常有效的。 有没有人有一些意见或建议?

编辑: 我落得这样做:

public long getLastTimestamp() 
    { 
     var filter = Builders<BsonDocument>.Filter.Exists("value"); 
     return getChannelNames() 
      .Select(channel => _database.GetCollection<BsonDocument>(channel.name)) 
      .SelectMany(channel => channel.FindAsync(filter).Result.ToList()) 
      .Max(docu => docu["_id"].ToInt64()); 
    } 
+0

你至少可以结合你的前两个'foreach'循环。 – C4u

+0

啊,是的。愚蠢的我不是:P固定! –

+0

最后两个循环也可以组合在一起。将项目添加到循环内的列表中,仅用于稍后再次循环此新列表是不必要的。 –

回答

2

检查了这一点:

public long getLastTimestamp() 
{ 
    //var tempList = getChannelNames(); 
    var channelList = new List<IMongoCollection<BsonDocument>>(); 
    var docuList = new List<BsonDocument>(); 

    foreach (var channel in getChannelNames()) 
    { 
     var filter = Builders<BsonDocument>.Filter.Exists("_id"); 
     var result = _database.GetCollection<BsonDocument>(channel.name) 
        .FindAsync(filter).Result.ToList(); 

     return result.Where(x => !x["_id"].IsObjectId) 
       .Max(entry => entry["_id"].ToInt64); 
    } 

    return 0; 
} 

不可能测试,因为这些物体ARNT提供给我。在linq部分,您可能必须转换为列表或数组才能获得Where()Max()

再次存储和迭代总是比较慢。

public long getLastTimestamp() 
{ 
    var filter = Builders<BsonDocument>.Filter.Exists("_id"); 

    return getChannelNames() 
    .Select(channel => _database.GetCollection<BsonDocument>(channel.name).FindAsync(filter).Result.ToList()) 
    .Where(doc => !doc["_id"].IsObjectId) 
    .Max(doc => doc["_id"].ToInt64); 
} 
+0

Linq并不意味着更好的表现。你可以检查这些扩展的代码,你会发现它通常不太好,因为它们管理更多的用例,然后执行更多的代码。 – Demonia

+1

@Demonia同意了。但它确实比复制收藏三次更高效。 –

+0

@Demonia我很喜欢用linq,因为它认为它会提供更好的性能。原来的那个在这个时候有一个'foreach',这是在一个条件下将数据保存到临时列表中。与linq一起去获取条件+获得最大价值是我认为没有任何暂时保存任何东西的正确的事情。 – C4u

2

这样的事情?

var filter = Builders<BsonDocument>.Filter.Exists("_id"); 

getChannelNames() 
    .SelectMany(channel => _database.GetCollection<BsonDocument>(channel.name)) 
    .SelectMany(channel => channel.FindAsync(filter).Result.ToList()) // Even better w/o ToList 
    .Where(docu => !docu["_id"].IsObjectId) 
    .Max(docu => docu["_id"].ToInt64()); 
+0

getChannelNames atm返回一个字符串列表我应该改变这个方法来返回其他东西吗 –

+0

它应该和字符串一起工作选择和SelectMany将你的输入数据转换成你在lambda函数中返回的任何类型,所以当第一个SelectMany执行时,你将收集通道名称(字符串,我猜);第二个将返回BsonDocuments的集合。然后Max会计算文档ID的最大值,这可能需要一些转换或者ToArray,ToList调用,但是想法是一样的。 –

+0

只是为了解释wh在我做了。我使用了使用foreach的SelectMany +直接添加解包集合,然后使用该集合将数据传递到下一个查询。 –