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

如何使用子查询返回的值列表查询类似于“Not IN”的mongob集合

沈健
2023-03-14

我是mongoDB的新手,使用2.6.4版。我被困在编写mongo查询和在这里寻求专家的帮助。

我在myCollection中有以下示例文档:

{   msgID: "1011",
    journalID: 1,   
    status: "FLAGGED",
    timeSent: ISODate("2015-10-27T03:44:19.359Z") },

{   msgID: "1012",
    journalID: 1,   
    status: "FLAGGED",
    timeSent: ISODate("2015-10-28T07:12:03.446Z") },

{   msgID: "1012",
    journalID: 2,   
    status: "INITIATED",
    timeReceived: ISODate("2015-10-28T08:06:21.221Z") },

{   msgID: "1013",
    journalID: 1,   
    status: "FLAGGED",
    timeSent: ISODate("2015-10-28T13:21:13.568Z") },

{   msgID: "1013",
    journalID: 2,   
    status: "INITIATED",
    timeReceived: ISODate("2015-10-28T13:56:06.419Z") },

{   msgID: "1013",
    journalID: 3,   
    status: "CLOSED",
    timeReceived: ISODate("2015-10-28T16:11:38.875Z") },

{   msgID: "1014",
    journalID: 1,   
    status: "FLAGGED",
    timeSent: ISODate("2015-10-29T13:21:13.568Z") },

{   msgID: "1015",
    journalID: 1,   
    status: "FLAGGED",
    timeSent: ISODate("2015-10-28T08:26:57.828Z") },

{   msgID: "1016",
    journalID: 1,   
    status: "FLAGGED",
    timeSent: ISODate("2015-10-28T11:03:09.075Z") },

{   msgID: "1016",
    journalID: 2,   
    status: "CLOSED",
    timeReceived: ISODate("2015-10-28T14:19:19.907Z") }

如何编写mongo查询,从满足以下条件的myCollection中提取文档:

  • 返回所有只有标记状态记录的msgID(即排除那些具有INITIATED或CLOSED状态条目的msgID)。
  • 以及时间发送的位置

预期结果为:

msgID     status        timeSent
-----     ---------     -----------------------------------
1011      FLAGGED       ISODate("2015-10-27T03:44:19.359Z")
1015      FLAGGED       ISODate("2015-10-28T08:26:57.828Z")

我知道在SQL中,这可以通过以下查询实现:

SELECT  m1.msgID, m1.status, m1.timeSent
FROM    myCollection m1
WHERE   m1.msgID NOT IN
            ( SELECT m2.msgID FROM myCollection m2 WHERE m2.status IN ('INITIATED', 'CLOSED'))
AND     m1.status = "FLAGGED"
AND     m1.timeSent < "10-29-2015 00:00:00"

任何帮助将不胜感激。

共有3个答案

尤钱明
2023-03-14

虽然它没有从性能角度进行优化,并且我了解存储和检索此类数据所需的架构更改,但为了与大家分享,我可以根据给定的数据结构找出查询:

db.myCollection.aggregate(
    { $group: {
      _id: "$msgID", stateChange: { $push: { status: "$status", timeSent: "$timeSent" }}}
    },
    { $match: {
        "stateChange.status": { $eq: 'FLAGGED', $nin: ['INITIATED','CLOSED'] }, 
        "stateChange.timeSent": { $lt: ISODate("2015-10-29T00:00:00")}}
    },
    { $unwind: "$stateChange" },
    { $project: {
        _id: 0, msgID: "$_id", status: "$stateChange.status", timeSent: "$stateChange.timeSent"}
    }
)
汤玉宸
2023-03-14

您可以使用查找()轻松做到这一点

db.collection.find(query, projection)

查询-指定选择条件(可选)更多(SQL中的WHERE子句)
投影-匹配文档中的所有字段(可选)

根据您的问题可以解决如下

  db.flagged.find({
        status: 'FLAGGED',
        timeSent: {
            $lt: ISODate('2015-10-29T00:00:00')
        },
        {msgID:1,status:1,timeSent:1}
    });

更多详细信息遵循mondb教程

农存
2023-03-14

就像前面提到的@BlakesSeven一样,最好更改模式。与其为每个状态添加文档,不如根据msgID对项目进行分组,并将项目添加到数组中。前三个文档如下所示:

{
    msgID: "1011",
    items: [{
        journalID: 1,   
        status: "FLAGGED",
        timeSent: ISODate("2015-10-27T03:44:19.359Z")
    }]
},
{
    msgID: "1012",
    items: [{
        journalID: 1,   
        status: "FLAGGED",
        timeSent: ISODate("2015-10-28T07:12:03.446Z")
    }, {
        journalID: 2,   
        status: "INITIATED",
        timeReceived: ISODate("2015-10-28T08:06:21.221Z")
    }]
}

这允许您以更好的性能进行更好的查询。您的查询如下所示:

db.getCollection('someCollection').find({
    items: {
        $size : 1
    },
    'items.status': 'FLAGGED'
});
 类似资料:
  • 我试图从表文章列表的文章与类别列表,每篇文章是列出的。假设文章“A”有3个类别“1”,“2”,“3”,我有一个以上的文章有一个以上的类别。我想在ArticleViewModel的列表中获得CategoryViewModel的列表。因为它是IEnumerableList,所以当我使用FirstOrDefault()时,我会在每个文章下获得相同的类别名称,但获得的文章数量是正确的。我如何才能获得类别名

  • 问题内容: 如何获取使用SQL Server的SQL查询返回的列数? 例如,如果我有如下查询: 它应该返回表A1中的总列数+表A2中的总列数。但是查询可能会更复杂。 问题答案: 这是一种方法: 您可以通过创建视图来执行类似的操作。

  • 问题内容: 假设您有数百个内存中对象的集合,并且需要查询此List以返回与某些SQL或Criteria(如查询)匹配的对象。例如,您可能有一个“汽车”对象列表,并且想要退回1960年代制造的所有汽车,并以AZ开头的车牌按汽车型号名称排序。 我知道JoSQL,是否有人使用过它,或者对其他/本地解决方案有任何经验? 问题答案: 我已经在生产应用程序中使用过Apache Commons JXPath 。

  • 我正在尝试计算配置单元中视图的平均/最小/最大记录计数 并试图实现如下内容: 但我收到一条错误消息: avg=5 min=4 max=6

  • 问题内容: 桌子: 我的查询: 我收到“ MySQL子查询返回多个行”错误。 我知道此查询可以使用以下查询的解决方法: 然后使用php循环遍历结果并执行以下查询以获取和回显它: 但是我认为可能会有更好的解决方案? 问题答案: 简单的解决方法是在子查询中添加一个子句: 一个更好的选择(就性能而言)是使用联接:

  • 问题内容: 我的查询导致以下错误: 消息512,级别16,状态1,过程Item_insupd,第17行 子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。 询问: 我怀疑这种情况的发生是因为我的子查询不包含,但是不幸的是,我不知道如何构造正确的子句。 问题答案: 我怀疑问题出在此字符串中(您的代码中的第26行): 看起来像返回多个行,所以您遇到了错