本文介绍了MongoDB C#使用“定义"构建器检索文档中数组中的所有匹配元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个结构类似嵌套子文档

I have a document that looks like this in structure with nested sub document

{
   "_id":ObjectId("50419077c2e6a1e18a489a0f"),
   "user":"Jone Doe",
   "fooArray":[
      {
         "plot":"circle",
         "color":"yellow",
      },
      {
         "plot":"circle",
         "color":"red",
      },
      {
         "plot":"square",
         "color":"green",
      }
   ]
}

我想在具有圆形图的本文档中检索fooArray中的所有匹配元素.

And I want to retrieve all the matching elements in fooArray in this document that has circular plot.

这是我尝试过的

var filter = FilterBuilder.filter.Eq(doc => doc.User, User);
var projection = ProjectionBuilder
                .Exclude(doc => doc.Id)
                .Exclude(doc => doc.User)
                .Include(doc => doc.FooArray)
                .ElemMatch(x => x.FooArray, y => y.Plot == "circle");

var definition = new OperationDefinitions<ShapeDocument> { Filter = filter };
            return await Performer.Perform(definition, async (def, collection) =>
            {
                var findResult = collection.Find(def.Filter).Project(projection);

                var result = await findResult.SingleOrDefaultAsync();
            });

这就是我得到的

{
   "fooArray":[
      {
         "plot":"circle",
         "color":"yellow",
      }
   ]
}

但是它只给我第一个匹配元素,而不是所有具有等于圆的图的元素

But it only gives me the first matching element instead of all the elements that have the plot equals to circle

{
   "fooArray":[
      {
         "plot":"circle",
         "color":"yellow",
      },
      {
         "plot":"circle",
         "color":"red",
      }
   ]
}

我确实阅读了mongodb文档,其中提到了

I did read the mongodb documentation which mentions

"$ elemMatch运算符将查询结果中字段的内容限制为仅包含与$ elemMatch条件匹配的第一个元素."

" The $elemMatch operator limits the contents of an field from the query results to contain only the first element matching the $elemMatch condition."

不太确定如何实现这一目标!

Not quite sure how to achieve this!

推荐答案

该问题并未完全描述用例,因此我根据一些假设为您提供了一些潜在的选择供您探索,尤其是它们取决于LINQ是否可用以及一次定位到单个文档(并且您可能不想要超出实际需要的代码):

The question doesn't fully describe the use case so I've come up with a few potential options for you to explore based on a few assumptions, in particular they depend on LINQ being available and to be targetting a single document at a time (and that you probably don't want more code than you really need):

1)您所拥有的产品有所不同.使用带有投影和LINQ表达式的标准find.

1) A variation on what you have. Use a standard find with a projection and LINQ expression.

var projection = Builders<ShapeDocument>.Projection
    .Expression(x => x.fooArray.Where(y => y.plot == "circle"));

var items1 = collection
    .Find(x => x.user == "Jone Doe")
    .Project(projection)
    .ToList();

2)使用聚合管道(您可以使用与上面相同的投影)

2) Use the aggregation pipeline (you could use the same projection as above)

var pipeline = collection
    .Aggregate()
    .Match(x => x.user == "Jone Doe")
    .Project(i => new
            {
                x = i.fooArray.Where(x => x.plot == "circle")
            });

var items2 = pipeline.SingleOrDefault();

3)将文档连同所有数组元素一起拉回,然后使用LINQ在本地进行过滤.从好的方面来说,这是少量的可读代码,但是,确实会在过滤之前将整个文档带回来.根据您的确切使用情况,这可能是可以接受的.

3) Pull the document back with all array elements then filter locally using LINQ. On the plus side this is a small amount of readable code, however, it does bring the entire document back before filtering. Depending on you're exact use this may well be acceptable.

var items3 = collection.AsQueryable()
    .SingleOrDefault(x => x.user == "Jone Doe")
    .fooArray.Where(x => x.plot == "circle");

如果不选择LINQ 真的,则有一个示例此处,其中显示了如何将投影转换为不使用LINQ.完全未经测试,但可能类似于:

If LINQ really isn't an option then there's an example here that shows how you might convert the projection to not us LINQ. Totally untested but would be something along the lines of:

var filter = new BsonDocument {
 {"input", "$items"},
 {"as", "item" },
 {"cond", new BsonDocument {
     // Fill in the condition values
     { "", new BsonArray { "", xxx } } }
   }
 };

var project = new BsonDocument {
 { "items", new BsonDocument { { "$filter", filter} } }
};

var pipeline = collection.Aggregate().Project(project);

这篇关于MongoDB C#使用“定义"构建器检索文档中数组中的所有匹配元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 02:41