c# - 在 Mongodb C# 中使用 AsQueryable 进行过滤 - ExpandoObject
问题描述
我正在尝试使用 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();
但我得到了这个例外:
System.InvalidOperationException HResult=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()
方法的是一个表达式树,它需要被翻译成 MongoDB 查询语言。C# 编译器将接受(extension method)ExpandoObject
之类的SingleOrDefault
方法,但是当需要将此类表达式树转换为 Mongo 查询时,这将在运行时失败。
ExpandoObject
使用 MongoDB 并没有什么特别之处。它必须以某种方式翻译成 BSON 文档(MongoDB 格式),例如下面的代码:
dynamic o = new ExpandoObject();
o.dateOfBith = new DateTime(2000, 1, 1);
r.Contents = o;
col.InsertOne(r);
ExpandoObject
以相同的方式插入,BsonDocument
或者Dictionary<string, T>
它只是变成:
{ "_id" : ObjectId(",,,"), "contents" : { "dateOfBith" : ISODate("2000-01-01T07:00:00Z") } }
在您的数据库中。
知道您可以使用点表示法构建查询。您还可以使用一个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();
推荐阅读
- profiling - Datadog 是否有能力从分析中排除某些网站?
- laravel - Laravel 通知上的 Laravel 5.5 批量分配异常错误 ID
- javascript - Javascript - 为 DOM 创建的元素创建切换功能
- php - Laravel 表单链接到错误的控制器功能
- javascript - 在 Chartjs 中动态更新数据
- javascript - React css 类名是全局的吗?
- python - 如何将两个列表项结果合二为一,以获得多个结果。在 selenium Webdriver 中使用 python
- c++ - 带有偏移设置的 Arduino MPU6050 AD0 技巧会导致数据损坏
- google-play - 封闭测试和内部测试轨道是否支持自动更新?
- c# - 使用经验规则估计有多少值低于特定偏差