如何查询mongodb集合类似于" NOT IN" with子查询返回的值列表

时间:2015-10-30 07:26:57

标签: mongodb

我是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中获取满足以下条件的文档:

  • 返回所有只有FLAGGED状态记录的msgID(即 排除那些具有INITIATED或CLOSED条目的msgID 状态)。
  • 并且timeSent< 2015年10月29日

预期结果为:

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 个答案:

答案 0 :(得分:4)

与提到的@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'
});

答案 1 :(得分:0)

您可以使用 find()

轻松完成此操作
db.collection.find(query, projection)
  

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

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

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

Mongdb Tutorial

之后的更多详细信息

答案 2 :(得分:0)

虽然它没有从性能点优化,我理解存储和检索此类数据所需的模式更改,但只是与所有人共享,我可以根据给定的数据结构找出查询:

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"}
    }
)