【问题标题】:Can Find() be called multipe times on a MongoCollection?可以在 Mongo 集合上多次调用 Find() 吗?
【发布时间】:2016-11-11 12:47:44
【问题描述】:

我正在尝试使用另一个对象 (MyObject) 上的属性值来更新对象数组中每个对象的属性。我不清楚是否打电话:

my_objects_collection = m_database.GetCollection(MY_OBJECTS_COLLECTION_NAME);

有任何性能影响,所以我尝试只调用一次并在 For... 循环中针对它执行一个新的 Find 命令(每次迭代都有一个修改的过滤器),见下文:

            MyObject my_object = null;
            IMongoCollection<MyObject> my_objects_collection = null;

            if (objects != null)
            {
               my_objects_collection = m_database.GetCollection<MyObject>(MY_OBJECTS_COLLECTION_NAME);

                for (int i = 0; i < objects.Count; i++)
                {
                    Expression<Func<MyObject, bool>> filter = x => (x.ID == objects[i].ID) && (x.LanguageCode == language_code);

                    my_object = await my_objects_collection.Find(filter).FirstOrDefaultAsync();

                    if (my_object != null)
                    { objects[i].DisplayName = my_object.Name; }
                }
            }

但是,上面的代码抛出了以下异常:

值不能为空。 参数名称:集合

在 MongoDB.Driver.Core.Misc.Ensure.IsNotNull[T](T value, String paramName) 在 MongoDB.Driver.IMongoCollectionExtensions.Find[TDocument](IMongoCollection1 collection, Expression1 过滤器,FindOptions 选项)

如果我将 my_objects_collection 赋值移动到 for 循环中,以便在每次迭代时调用它,则代码可以正常工作而不会引发任何异常。

因此我的问题是,在对 MongoCollection 引用 (my_objects_collection) 执行 Find(或任何其他操作)之后会发生什么情况?

如果有人能对此提供一些见解,我将不胜感激。我可以继续,因为我的应用程序正在运行,但我真的很想知道为什么它会抛出一个异常,表明集合为空,以我自己的理解。

提前谢谢你,

安德鲁

【问题讨论】:

    标签: c# mongodb


    【解决方案1】:

    无论您的例外情况如何,您都不需要为检索到的每条记录执行查找,您可以使用 $in 运算符实现此目的。

    然后您可以循环结果集并对每个文档执行更新。这要高效得多,因为您对数据库执行单个操作以返回记录,然后为每次更新执行一个操作。而不是每次检索一个,每次更新一个。

    Builders<MyObject>.Filter.In
    

    如果你想匹配嵌入数组中的元素,你可以使用

    Builders<MyObject>.Filter.ElemMatch
    

    一个快速(未经测试的)示例

    if (objects != null)
    {
        var my_objects_collection = m_database.GetCollection<MyObject>(MY_OBJECTS_COLLECTION_NAME);
    
        var filterBuilder = Builders<MyObject>.Filter;
    
        var inFilter = filterBuilder.In(x => x.ID, objects.Select(x => x.ID));
        var andFilter = filterBuilder.And(
            inFilter, 
            filterBuilder.Eq(x => x.LanguageCode, language_code)
        );
    
        var results = await my_objects_collection.Find(andFilter).ToListAsync();
    
        foreach(var result in results)
        {
            //result is going to the a database object returns which matched your filter
        } 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-10
      • 1970-01-01
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 1970-01-01
      相关资源
      最近更新 更多