gpt4 book ai didi

c# - MongoDB 数组查询

转载 作者:可可西里 更新时间:2023-11-01 09:52:11 26 4
gpt4 key购买 nike

我是 Mongo DB 的新手,我正在尝试弄清楚如何执行一些更复杂的查询。我有一个包含 DateTime 嵌套数组的文档。

这是我的数据:

{ "_id" : ObjectId("537d0b8c2c6b912520798b76"), "FirstName" : "Mary", "LastName" : "Johnson", "Age" : 27, "Phone" : "555 555-1212", "Dates" : [ISODate("2014-05-21T21:34:16.378Z"), ISODate("1987-01-05T08:00:00Z")] }

{ "_id" : ObjectId("537e4a7e2c6b91371c684a34"), "FirstName" : "Walter", "LastName" : "White", "Age" : 52, "Phone" : "800 123-4567", "Dates" : [ISODate("1967-12-25T08:00:00Z"), ISODate("2014-12-25T08:00:00Z")] }

我想要做的是返回文档,其中 Dates 数组包含一个范围内的值。在我的测试用例中,范围是 1/1/1987 和 1/10/1987 所以我希望得到上面列出的第一个文档(Mary Johnson),因为 1/5/1987 在那个 Dates 数组中并且落在 1/1 之间/1987 年和 1/10/1987。

我希望能够同时使用 MongoDB 命令行实用程序和 C# 驱动程序来执行此操作。

使用 C# 驱动程序,我尝试了以下 LINQ 查询(基于 MongoDB 文档中的示例):

DateTime beginRange = new DateTime(1987, 1, 1);
DateTime endRange = new DateTime(1987, 1, 10);

var result = from p in people.AsQueryable<Person>()
where p.Dates.Any(date => date > beginRange && date < endRange)
select p;

上述代码从 C# 驱动程序代码中抛出异常:

Any 仅支持序列化为文档的项目。当前的序列化程序是 DateTimeSerializer,并且必须实现 IBsonDocumentSerializer 才能参与 Any 查询。

当我尝试直接查询 MongoDB 数据库时,我尝试了以下操作:

db.People.find( {Dates: { $gt: ISODate("1987-01-01"), $lt: ISODate("1987-01-10") } } )

此查询会返回两个文档,而不仅仅是 Dates 数组中包含 1/5/1987 的文档。

编辑:

我从 C# 驱动程序中找到了一种方法。它没有我想要的那么干净,但它是可行的。

我认为,既然有一种方法可以直接从命令实用程序中获取我想要的内容,那么也必须有一种方法可以从 C# 驱动程序中获取我想要的内容,只需从 C# 驱动程序中执行相同的查询即可。

string command = "{Dates : { $elemMatch : { $gt: ISODate(\"" + beginRange.ToString("yyyy-MM-dd") + "\"), $lt: ISODate(\"" + endRange.ToString("yyyy-MM-dd") + "\") } } } ";
var bsonDoc = BsonSerializer.Deserialize<BsonDocument>(command);
var queryDoc = new QueryDocument(bsonDoc);
MongoCursor<Person> p = people.Find(queryDoc);

最佳答案

C#驱动

正如异常提示的那样,只要您的数组是原始类型 (DateTime) 而不是真正的文档,您就无法使用 C# 驱动程序执行您想执行的操作。

来自MongoDB Linq 任何描述:

This will only function when the elements of the enumerable are serialized as a document. There is a server bug preventing this from working against primitives.

我想您可以围绕 DateTime 值创建一个文档包装器,这样您仍然可以这样做:

var result = people.AsQueryable<Person>().Where(
person => person.Dates.Any(date =>
date.Value > beginRange && date.Value < endRange));

.

public class DocumentWrapper<T>
{
public ObjectId Id { get; private set; }
public T Value { get; private set; }

public DocumentWrapper(T value)
{
Id = ObjectId.GenerateNewId();
Value = value;
}
}

原生查询

至于您的查询,它实际上并不等同于 Linq 查询。那将是:

{ 
Dates :
{
$elemMatch :
{
$gt: ISODate("1987-01-01"),
$lt: ISODate("1987-01-10")
}
}
}

有关 $elemMatch 的更多信息 here

关于c# - MongoDB 数组查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23816456/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com