c# - 在 Mongodb C# 中使用 AsQueryable 进行过滤 - ExpandoObject

标签 c# mongodb linq mongodb-.net-driver

我正在尝试使用 AsQueryable 和 LINQ 函数查询 mongodb 数据库。

我当前的数据库结构是我有一些集合,主要是在 C# 中定义的记录,如下所示:

public class Record  
    {
        [BsonElement("formName")]
        public string FormName { get; set; }

        [BsonElement("created")]
        public DateTime Created { get; set; }

        [BsonElement("createdBy")]
        public string CreatedBy { get; set; }

        [BsonId]
        [BsonIgnoreIfDefault]
        [BsonRepresentation(BsonType.ObjectId)]
        private string InternalId { get; set; }

        [BsonElement("recordId")]
        [Newtonsoft.Json.JsonProperty("recordId")]
        public string Id { get; set; }

        [BsonElement("organisationId")]
        public string OrganisationId { get; set; }

        // TODO: Consider making configurable
        private string appName = "MediLog";

        [BsonElement("appName")]
        public string AppName
        {
            get { return this.appName; }
            set { this.appName = value; }
        }

        [BsonElement("schemaVersion")]
        public int SchemaVersion { get; set; }

        [BsonElement("contents")]
        public ExpandoObject Contents { get; set; }

        [BsonElement("modified")]
        public DateTime Modified { get; set; }

        [BsonElement("modifiedBy")]
        public string ModifiedBy { get; set; }

        [BsonElement("majorVersion")]
        public int MajorVersion { get; private set; }

        [BsonElement("minorVersion")]
        public int MinorVersion { get; private set; }

        [BsonElement("version")]
        public string Version
        {
            get
            {
                return (MajorVersion + "." + MinorVersion);
            }

            set
            {
                MajorVersion = Convert.ToInt32(value?.Substring(0, value.IndexOf(".", StringComparison.OrdinalIgnoreCase)), CultureInfo.InvariantCulture);
                MinorVersion = Convert.ToInt32(value?.Substring(value.IndexOf(".", StringComparison.OrdinalIgnoreCase) + 1), CultureInfo.InvariantCulture);
            }
        }

    }

就您而言,数据主要存储在 Contents 中,它是一个 ExpandoObject,这就是我的问题所在。

我正在尝试做这样的事情:

 var collection =
                database.GetCollection<Record>("recordData").AsQueryable()
                    .Where(x =>  x.Contents.SingleOrDefault(z => z.Key == "dateOfBirth").Value.ToString().Length > 0)
                        .ToList();  

但我得到了这个异常(exception):

系统.InvalidOperationException H结果=0x80131509 Message={document}{contents}.SingleOrDefault(z => (z.Key == "dateOfBirth")).Value.ToString().Length 不受支持。

另外,当我尝试时:

  var collection1 = database.GetCollection<Record>("recordData").AsQueryable()
                .Where(x => (DateTime)(x.Contents.SingleOrDefault(z => z.Key == "dateOfBirth").Value)  > DateTime.Now)
                .ToList();

我得到这个异常:

System.InvalidOperationException
  HResult=0x80131509
  Message=Convert({document}{contents}.SingleOrDefault(z => (z.Key == "dateOfBirth")).Value) is not supported.

另外,当我这样做时:

var collection =
database.GetCollection(“recordData”).AsQueryable()
.Where(x => (DateTime)x.Contents.First(z => z.Key == “dateOfBirth”).Value > DateTime.Now ).ToList();

我收到此异常:

System.NotSupportedException: ‘The expression tree is not supported: {document}{contents}’

所以我的问题实际上是如何使用 AsQueryable 和 LINQ 对 ExpandoObject 类型的对象运行查询。

谢谢!

最佳答案

无论你想传递什么给 .Where() method 是一个表达式树,需要翻译成 MongoDB 查询语言。 C# 编译器将接受 ExpandoObject的方法如 SingleOrDefault (扩展方法)但是当此类表达式树需要转换为 Mongo 查询时,这在运行时会失败。

ExpandoObject 没什么特别的当您使用 MongoDB 时。它必须以某种方式翻译成 BSON 文档(MongoDB 格式),例如下面的代码:

dynamic o = new ExpandoObject();
o.dateOfBith = new DateTime(2000, 1, 1);
r.Contents = o;
col.InsertOne(r);

插入ExpandoObjectBsonDocument 相同或Dictionary<string, T>所以它就变成了:

{ "_id" : ObjectId(",,,"), "contents" : { "dateOfBith" : ISODate("2000-01-01T07:00:00Z") } }

在您的数据库中。

知道您可以使用 the dot notation 构建查询。还有一个StringFieldDefinition您可以使用的类,因为您无法从 ExpandoObject 构建表达式树以强类型的方式:

var fieldDef = new StringFieldDefinition<Record, DateTime>("contents.dateOfBith");
var filter = Builders<Record>.Filter.Gt(fieldDef, new DateTime(2000, 1, 1));

var res = col.Find(filter).ToList();

关于c# - 在 Mongodb C# 中使用 AsQueryable 进行过滤 - ExpandoObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61851443/

相关文章:

c# - 从 ASP.net 的提醒开始

c# - wcf + 响应消息的内容类型text/html与绑定(bind)的内容类型不匹配(application/soap+xml; charset=utf-8)

c# - 如何在 C# 中将字符串格式化为电话号码

python - 为什么 pymongo 在对不同对象使用 insert_one 时会生成重复的 _id 值?

node.js - prisma 容器中的 AWS ECS 错误 - 环境变量 PRISMA_CONFIG

c# - 从通用列表中删除属性/列

c# 如何从日期中删除上午/下午

java - MongoDB : find matching elements in an array with given attributes using java driver

c# - 查找与其他列表元素有 3 个属性相似的列表元素,然后将第二个元素的值添加到第一个元素

c# - 当所有表达式都具有相同类型时,在一种情况下会出现编译错误,而在另一种情况下不会