当前位置: 首页 > 知识库问答 >
问题:

MongoDb C#驱动程序与组和项目使用Aggregate()查询给予异常

左丘嘉言
2023-03-14

我正在开发使用MongoDb作为数据库和的应用程序。Net核心3.0作为框架。为了从数据库中获取数据,我创建了一个DbContext类,并使用MongoDbAggregation()功能。我无法通过适当的投影。下面是DbContext的代码。cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;

    namespace Test.DbContext
    {
        /// <summary>
        /// Standard CRUD Operations with MongoDb  
        /// </summary>
        public class MongoDbContext   
        {
            #region Properties
            private readonly IMongoClient _mongoDbClient = null;

            private readonly IMongoDatabase _mongoDb = null;
            #endregion

            #region Constructor
            public MongoDbContext(IOptions<MongoSetting> mongoConfigs)
            {
                _mongoDbClient = new MongoClient(mongoConfigs.Value.ConnectionString);
                _mongoDb = _mongoDbClient.GetDatabase(mongoConfigs.Value.DatabaseName);
            }
            #endregion

            #region Grouping
            public IList<TProjection> GroupBy<TDocument, TGroupKey, TProjection> 
            (FilterDefinition<TDocument> filter, 
             Expression<Func<TDocument, TGroupKey>> selector, 
             Expression<Func<IGrouping<TGroupKey, TDocument>, TProjection>> projection){
                   return _mongoDb.GetCollection<TDocument>("collectionName").Aggregate().Match(filter).Group(selector, projection).ToList();
               }   
            #endregion
        }
    }

要调用函数GroupBy(),我必须通过过滤器、选择器和投影,但无法构建适当的表达式。以下是数据模型和调用函数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.Extensions.Options;
using MongoDB.Driver;

namespace Test 
{
    [BsonIgnoreExtraElements]
    public class Employee   
    {
        [BsonId]
        [BsonElement("_id")]
        [BsonRepresentation(BsonType.ObjectId)]
        public ObjectId Id { get; set; }

        [BsonElement("type")]
        [JsonProperty("type")]
        public string Type { get; set; }

        [BsonElement("id")]
        public string CustomerId { get; set; }

        [BsonElement("name")]
        public string CustomerName { get; set; }
    }
}

我将客户存储库中的dbContext称为:

using System;
using System.Linq.Expressions;
using MongoDB.Driver;

namespace Test.Repositories
{
    public class CustomerRepository : ICustomerRepository
    {
        #region Properties
        private readonly IMongoDbContext _dbContext = null;
        #endregion

        #region Constructor
        public CustomerRepository(IMongoDbContext dbContext)
        {
            _dbContext = dbContext;
        }
        #endregion

        #region Methods
        public EmployeeCollection GetSpecificData()
        {

            Expression<Func<Employee, dynamic>> filter = x => x.Employee.CustomerId == "11";
            Expression<Func<Employee, dynamic>> selector = x => new { typeName = x.Employee.Type };
            Expression<Func<IGrouping<dynamic, Employee>, dynamic>> projection = x => new
            {
                Key = x.Key,
                count = x.Count(),
                avgValue = x.Average(x => Convert.ToInt32(x.Employee.CustomerId))
            };


            var result = _dbContext.GroupBy<Employee, dynamic, dynamic>(filter, selector, projection);

            // Giving exception
            // "Value type of serializer is <>f__AnonymousType0`1[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, 
            //PublicKeyToken=7cec85d7bea7798e]] and does not match member type System.Object. (Parameter 'serializer')"
        }
        #endregion
    }
}

例外情况:

“序列化程序的值类型为

共有1个答案

齐坚成
2023-03-14

我认为你想做的事不可行。作为替代方案,我可以建议公开。从dbContext中聚合(),并从repo中查询,如下所示。

雇员阶级

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace Test
{
    [BsonIgnoreExtraElements]
    public class Employee
    {
        [BsonId]
        [BsonElement("_id")]
        [BsonRepresentation(BsonType.ObjectId)]
        public ObjectId Id { get; set; }

        [BsonElement("type")]
        public string Type { get; set; }

        [BsonElement("id")]
        [BsonRepresentation(BsonType.String)] // to avoid manual conversion
        public int CustomerId { get; set; }

        [BsonElement("name")]
        public string CustomerName { get; set; }
    }
}

DB上下文

using MongoDB.Driver;
using System.Linq;

namespace Test.DbContext
{
    public class MongoDbContext
    {
        private readonly IMongoClient _mongoDbClient = null;

        private readonly IMongoDatabase _mongoDb = null;

        public MongoDbContext()
        {
            _mongoDbClient = new MongoClient("mongodb://localhost");
            _mongoDb = _mongoDbClient.GetDatabase("test");
        }

        public IAggregateFluent<TDocument> Aggregate<TDocument>() =>
            _mongoDb.GetCollection<TDocument>(nameof(TDocument)).Aggregate();

    }
}

存储库

using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;
using Test.DbContext;

namespace Test.Repositories
{
    public class CustomerRepository
    {
        private static readonly MongoDbContext _dbContext = new MongoDbContext();

        public List<dynamic> GetSpecificData()
        {
            var result = _dbContext.Aggregate<Employee>()
                             .Match(e => e.CustomerId == 11)
                             .Group(e => e.Type, g => new { Key = g.Key, Count = g.Count(), Average = g.Average(e => e.CustomerId) })
                             .ToList();

            return result.Cast<dynamic>().ToList();
        }
    }
}

我还建议您不要将匿名类型转换为动态类型。因此,创建并使用另一个类(用于组结果)来保留类型安全。

我还可以推荐你看看我写的一个库,它消除了编写自己的dbContext的需要。

然后看看这个初学者模板项目,看看它在使用中。

 类似资料:
  • 我试图在MongoDB\驱动程序\查询中使用选项: 如果$选项似乎可以: --------$options: 数组([排序]= $query没有给我好的选项: 限制和批量大小不等于20,为什么?请问怎么办? 提前感谢

  • 我总是读到MongoDB驱动程序(>2.0)for NodeJS支持承诺。但我找到的仅有的例子是connect()和findOne()函数。虽然它适用于这些,而且我可以得到承诺,但对于aggregate()和find()它不适用。我明白这是因为它们可能会返回游标,但是既然有承诺支持,那些承诺在哪里呢?一定有办法和他们合作。欢迎提供链接、示例或简单解释:) 谢谢你,乔迪。

  • 问题内容: 我有一个使用mongodb本机驱动程序的node.js应用程序。在使用节点v8.9.1将应用程序代码迁移到异步/等待的过程中,我努力寻找一种适合mongodb查询的好方法。mongodb驱动程序的主要问题是,所有查询都使用回调,其中对异步方法来说,promise函数是必需的。 备择方案: 猫鼬 -承诺不赞成使用查询,它会强制使用Schema模型,这对我的应用程序来说有点开销。 mong

  • 通过使用MongoDB和Java驱动程序,我有一个用户集合,我想根据他们的ObjectId进行查询(总体情况:我从ObjectId推断出对象的创建时间戳)。 问题是,用ObjectId查询似乎不起作用:我总是没有结果。为了测试的目的,我在搜索查询中硬编码了数据库中现有用户的ObjectId,只是为了确保我能得到结果: {“_id”:ObjectId(“565ef85ee4b0a4db3c2fc96

  • 我是Gradle项目的新手,我有一个问题。我在网上搜索过,但找不到我需要的东西,或者我不知道如何搜索。首先我要告诉你我的情况。我有一个Gradle项目,我想在将来与jenkins一起执行几个自动化测试,但现在我想在Eclipse上进行尝试。我在/lib目录中有oracle jdbc驱动程序,这是我的构建。格拉德尔 我想在一个类中使用这个jdbc驱动程序,但我不知道如何使用它。当我尝试使用Maven

  • 在本教程中,http://www.sqlitetutorial.net/sqlite-java/sqlite-jdbc-driver/,关于将sqlite与java结合使用,首先从以下网站下载JDBC驱动程序,https://bitbucket.org/xerial/sqlite-jdbc/downloads/.然后使用Maven构建系统将驱动程序添加到项目中。 我环顾四周,看不出如果你使用Gra