【问题标题】:How to project selected fields from a document in mongoose based on conditions如何根据条件从猫鼬中的文档中投影选定的字段
【发布时间】:2017-02-18 20:15:23
【问题描述】:

我的文档结构是这样的。我在哪里存储所有基于时间戳的事件。我的文档是这样的

[
  {
    "_id": {
      "$oid": "589341cff92be305c034cb5a"
    },
    "__v": 0,
    "name": "TV",
    "switch_event": [
      {
        "timestamp": 1486186277826,
        "event_type": "on"
      },
      {
        "timestamp": 1486272677826,
        "event_type": "off"
      },
      {
        "timestamp": 1486099877826,
        "event_type": "off"
      },
      {
        "timestamp": 1486186277826,
        "event_type": "on"
      },
      {
        "timestamp": 1486272677826,
        "event_type": "off"
      },
      {
        "timestamp": 1486099877826,
        "event_type": "off"
      }
    ]
  }
]

现在在查询此文档时,我只对今天发生的事件感兴趣。所以在查询这个之后我正在写这样的投影查询(为了测试我保持时间戳> 0,这应该给出所有事件) -

SwitchAppliance.find({_id:"589341cff92be305c034cb5a"},{
                name:1,
                switch_event:{$elemMatch: {
                    timestamp: {
                                $gt:0
                    }
                }}
         },(err,results)=>{
            if(err) {console.log(err);return next({message: "Internal Server Error"});}
            return res.json(results);
        } ); 

但是当我得到结果时,我只在 switch_event 数组中得到一个事件对象——像这样——

[
  {
    "_id": "589341cff92be305c034cb5a",
    "switch_event": [
      {
        "_id": "589567251c653a0890b8b1ef",
        "event_type": "on",
        "timestamp": 1486186277826
      }
    ],
    "name": "TV"
  }
]

【问题讨论】:

  • 查询投影 $elemMatch 只返回第一个匹配元素。您需要使用聚合来获取所有匹配的元素。不过,该模式似乎不是这个用例的最佳选择——这些数组到底能有多大?
  • 真正的大...
  • 这是一个更适合 MongoDB 用户 Google 小组的讨论,但您可以在 MongoDB 中搜索将不断增长的数组存储在单个文档中的问题,有很多关于此的文章。
  • 谢谢@AsyaKamsky,你能帮我做聚合查询吗,我试着写了,但是没有用。
  • 如果您将所有事件保存在一个数组中,您的架构将无法扩展,因此聚合只会延迟问题。

标签: mongodb mongoose mongodb-query


【解决方案1】:

您正在针对new Date()(日期对象)查询Date.now()(时间戳或数字)。快速控制台测试显示以下内容:

> typeof Date.now()
=> "number"
> typeof new Date()
=> "object"

所以首先,我会改变

var today = new Date();

到

var today = Date.now();

然后你错过了“时间戳”不包含日期值,而是另一个对象,其中包含一个带有键 $date 和日期作为值的项目。因此,您的查询可能类似于以下内容:

var today = Date.now();
Item1.find({}).populate({
  path:"item1",
  select: {
    name:1,
    event:{
      $elemMatch: {
        timestamp: {
          date: {
            $gte:today
          }
        }
      }
    }
  }
})

【讨论】:

  • 我很感激,但它不起作用。我今天更改为 Date.now(),并且还使用了您的查询(在将 'date' 替换为 '$date' 之后)。但看起来这些事情是猫鼬自动理解的,我们不需要这样做。无论如何,重点是,即使在此查询之后我得到相同的结果,我也只会在事件数组中附加一个对象。像这样-“事件”:[{“_id”:“589567251c653a0890b8b1ed”,“event_type”:“off”,“timestamp”:1486099877826}]
  • 我尝试将时间戳字段更改为数字类型,然后它唯一的数字比较问题。它仍然只返回结果文档中的一个对象。哪个是最后一个对象。
【解决方案2】:

终于,在这里找到了钥匙。

Unwind empty array in mongodb

@ivan.srb 的答案派上了用场。 终于做了这样的事情 -

SwitchAppliance.aggregate([
                {$match:{_id:{$in : switch_appliances_array}}},

                {$project:{
                   switch_no:1,switch_name:1,switch_type:1,appliance_type:1,sboard_id:1,current_status:1,
                   switch_event : { $cond : [ { $eq : [ "$switch_event", [] ] }, [ { timestamp : 0 , event_type:"off"} ], '$switch_event' ] } 
                }},
                {$unwind:"$switch_event"},

                {$match:{$or: [{"switch_event.timestamp":{$gt:now}},{ "switch_event.timestamp":0} ]}},

                {$group:{
                    _id:"$_id",
                    switch_no:{$first:"$switch_no"},
                    switch_type:{$first:"$switch_type"},
                    switch_name:{$first:"$switch_name"},
                    appliance_type:{$first:"$appliance_type"},
                    current_status:{$first:"$current_status"},
                    switch_events:{$push:"$switch_event"}
                }},

【讨论】:

  • 感谢您的回答!救了我一天。
猜你喜欢
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多