You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB中使用$in匹配数组变量无结果?求正确实现方法

问题场景

现有test_collection集合数据如下:

{
    "event_type" : "ENTRY",
    "DateTime" : ISODate("2024-02-08T00:00:00.000+0000")
},
{
    "event_type" : "ENTRY",
    "DateTime" : ISODate("2024-02-09T00:00:00.000+0000")
},
{
    "event_type" : "ENTRY",
    "DateTime" : ISODate("2024-02-10T00:00:00.000+0000")
},
{
    "event_type" : "DELETE",
    "DateTime" : ISODate("2024-02-10T00:00:00.000+0000")
},
{
    "event_type" : "DELETE",
    "DateTime" : ISODate("2024-02-24T00:00:00.000+0000")
}

需求是找出所有DateTime与任意DELETE类型文档DateTime匹配的ENTRY文档,编写的Shell脚本如下:

var col = db.getCollection("test_collection");

var delete_dates = col.find({"event_type" : "DELETE" }).map(function(x) {return  x.DateTime});
col.find({"event_type" : "ENTRY", "DateTime" : {$in : delete_dates}});

实际运行时,delete_dates数组确实包含两个预期的日期值,但查询返回空结果;而将{$in : delete_dates}替换为{$in : [ ISODate("2024-02-10T00:00:00.000+0000"), ISODate("2024-02-24T00:00:00.000+0000")]}则能正常返回结果。

问题原因

通过find().map()获取的delete_dates数组元素是JavaScript原生Date对象,而MongoDB集合中存储的DateTime是BSON规范的ISODate类型(Mongo Shell中显示为ISODate(...))。尽管两者代表的时间数值相同,但MongoDB查询会进行严格的类型匹配,JS原生Date对象无法匹配集合中的BSON日期类型数据,因此返回空结果。手动调用ISODate()构造函数生成的是符合BSON规范的日期对象,所以能正确匹配。

解决方法

方法1:显式转换为BSON日期对象

在map函数中将JS Date对象转换为Mongo Shell的ISODate对象:

var col = db.getCollection("test_collection");
var delete_dates = col.find({"event_type": "DELETE"}).map(function(x) {
    return ISODate(x.DateTime.toISOString());
});
col.find({"event_type": "ENTRY", "DateTime": {$in: delete_dates}});

方法2:通过聚合直接提取BSON日期数组

使用聚合查询的$push操作直接从集合中提取BSON日期数组,避免类型转换问题:

var col = db.getCollection("test_collection");
var delete_dates = col.aggregate([
    {$match: {"event_type": "DELETE"}},
    {$group: {_id: null, dates: {$push: "$DateTime"}}}
]).toArray()[0].dates;
col.find({"event_type": "ENTRY", "DateTime": {$in: delete_dates}});

方法3:单步聚合查询(更高效)

无需提前获取日期数组,直接用聚合关联查询完成需求,减少客户端与服务器的交互:

db.getCollection("test_collection").aggregate([
    {$match: {"event_type": "ENTRY"}},
    {$lookup: {
        from: "test_collection",
        localField: "DateTime",
        foreignField: "DateTime",
        as: "matches"
    }},
    {$match: {"matches.event_type": "DELETE"}},
    {$project: {matches: 0}} // 移除冗余的matches字段
]);

内容的提问来源于stack exchange,提问作者EatATaco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:33:28