MongoDB查询 - 返回切片数组

时间:2014-03-17 11:49:00

标签: mongodb mongoose coffeescript aggregation-framework database

我正在尝试在以下架构上指定特定查询:

executionSchema = new Schema(
  timestamp: {type: Number},
  components: [{
    uid: { type: String },
    type: { type: String },
    control_ports: [ { name: String, values: [type: Number] } ]
    input_samples: [ { name: String, values: [type: Number] } ]
    output_samples: [ { name: String, values: [type: Number] } ]
    execution_times: [type: Number]
  }]
)

我想返回一个带有切片数组的组件(input_samples和output_samples),由时间戳指定。这是我到目前为止所做的:

exports.getSamples = (req, res) ->
    timestamp = req.param("timestamp")
    uid = req.param("uid")
    skip = req.param("skip")
    amount = req.param("amount")
    #query = Execution.findOne({'timestamp':timestamp}, 'components.input_samples components.output_samples')
    query = Execution.findOne({'timestamp':timestamp})
    query.where('components.uid').equals(uid)
    query.slice('components.input_samples.values', 5)
    query.slice('components.output_samples.values', 5)
    query.select('components.$.')
    #query.slice('values', 5)
    query.exec ( err, samples )->
        if err
            console.log "Error: "
            console.log err
            res.json err
        else
            console.dir samples
            res.json samples
        return
    return

它实际上返回正确的组件位,它包含数组内的每个元素。不知何故,我设法用另一个查询切片数组,但结果包含每个可用的组件。我想我还是要习惯MongoDb ..

谢谢。

修改 这就是我得到的:

{
    "_id": "5326ca6558f41c510a2659ad",
    "components": [
      {
        "uid": "sine#0",
        "type": "SW",
        "_id": "5326ca6558f41c510a2659b5",
        "execution_times": [
          500,
          450,
          700
        ],
        "output_samples": [
          {
            "name": "Output_Port",
            "_id": "5326ca6558f41c510a2659b6",
            "values": [
              0,
              0.8414709848078965,
              0.9092974268256817,
              0.1411200080598672,
              -0.7568024953079282,
              -0.9589242746631385,
              -0.27941549819892586,
              0.6569865987187891,
              0.9893582466233818,
              0.4121184852417566,
              ...,
              -0.5440211108893698,
              -0.9999902065507035,
              0.5878193939808536,
              0.9983436270438855,
              0.4909953335002932
            ]
          }
        ],
        "input_samples": [],
        "control_ports": [
          {
            "name": "Control 1",
            "_id": "5326ca6558f41c510a2659b7",
                      "values": [
              0,
              0.8414709848078965,
              0.9092974268256817,
              0.1411200080598672,
              -0.7568024953079282,
              -0.9589242746631385,
              -0.27941549819892586,
              0.6569865987187891,
              0.9893582466233818,
              0.4121184852417566,
              ...,
              -0.5440211108893698,
              -0.9999902065507035,
              0.5878193939808536,
              0.9983436270438855,
              0.4909953335002932
            ]
          }
        ]
      }
    ]

和我想要的(返回这些数组的子集):

  {
    "_id": "5326ca6558f41c510a2659ad",
    "components": [
      {
        "uid": "sine#0",
        "type": "SW",
        "_id": "5326ca6558f41c510a2659b5",
        "execution_times": [
          500,
          450,
          700
        ],
        "output_samples": [
          {
            "name": "Output_Port",
            "_id": "5326ca6558f41c510a2659b6",
            "values": [
              0,
              0.8414709848078965,
              0.9092974268256817,
              0.1411200080598672,
              -0.7568024953079282,
              -0.9589242746631385
            ]
          }
        ],
        "input_samples": [],
        "control_ports": [
          {
            "name": "Control 1",
            "_id": "5326ca6558f41c510a2659b7",
                      "values": [
              0,
              0.8414709848078965,
              0.9092974268256817,
              0.1411200080598672,
              -0.7568024953079282
            ]
          }
        ]
      }
    ]

编辑2:

  

所以这确实会引起质疑,"你真的想要拥有数组"?只是这样说,因为当信息被呈现时,那么实际数组的唯一部分似乎是"值"领域。

我猜数据比你想象的要复杂一点。组件阵列可以容纳任意数量的组件,具有独特的" uids"对于每个"执行"可以是不同的。因此,我想我必须使用数组作为组件。

  

在这种情况下,$ slice的问题在于你实际上并不知道"哪个"数组元素从嵌套中进行操作。因此,您呈现的样式将无法工作,因为元素可能是任何可能的索引。正确的形式,如果它被支持,它不是这样的:

数组内特定组件的位置是我不知道的唯一索引,因为数据创建应用程序在更新值之前初始化执行。因此,我只需要一个单独的位置$运算符'。它应该看起来像{ "components.$.output_samples.0.values": { "$slice": 5 } }

  

嵌套列表将成为各种问题的一个问题,并且因更新而臭名昭着。如果可能,您应该考虑替代方案在这种情况下,如果要限制输出,那么唯一可行的方法是检索整个文档,然后在代码中处理数组以限制返回的结果。

我想简化我的真实意图是一个小错误。我想使用切片运算符跳过前n个元素并检索以下m个元素。这两个变量应由用户指定。但是,output_samples.0.values字段可能包含数百万个值。甚至更多。这就是为什么我想收集与用户需求一样多的值。

我非常感谢你的详细解答。

1 个答案:

答案 0 :(得分:4)

此处您将遇到$slice的问题或任何类型的数组投影都是您在已定义的模式中嵌套数组的事实。我还注意到使用positional $运算符偷偷摸摸地偷看,所以最好在文档的上下文中解释。

所以在那个页面上有这样的:

  
      
  • $ projection运算符将字段内容限制为与查询文档匹配的第一个元素。
  •   
  • 字段必须出现在查询文档
  • 中   

首先,对于初学者,您不会在查询中询问匹配任何数组的任何元素中的特定字段。仅凭这一点,就不会有匹配元素的投影。在任何情况下,只有第一个匹配的数组元素才能可能匹配,即使您这样做了。

在您的结构中,您唯一可以匹配的是数组“组件”中的顶部位置。在顶部。

在此上下文中$slice的问题是您实际上不知道“which”数组元素在嵌套之外进行操作。因此,您呈现的样式将不起作用,因为元素可能是任何可能的索引。正确的表单,如果支持,并且,则类似于:

{ "components.0.output_samples.0.values": { "$slice": 5 } }

因为您需要指定您实际谈论的元素的索引路径。

所以这确实会带来质疑,“你真的意味着拥有数组”吗?只是这样说,因为当信息被呈现时,实际数组中唯一的部分似乎是“values”字段。

嵌套列表将成为各种问题的一个问题,并且因更新而臭名昭着。如果可能,您应该考虑替代方案在这种情况下,如果要限制输出,那么唯一可行的方法是检索整个文档,然后在代码中处理数组以限制返回的结果。

即使是以下“非常复杂”的咒语只会在其现有形式中起作用(“有点”),因为所有“其他”数组嵌套有一个< em>一个元素。所以它使这成为可能,但不切实际

db.components.aggregate([
   { "$unwind": "$components" },
   { "$unwind": "$components.output_samples"},
   { "$unwind": "$components.control_ports"},
   { "$unwind": "$components.output_samples.values"},
   { "$limit": 5 },
   { "$group": { 
       "_id": { 
           "_id": "$_id", 
           "components": {
               "uid": "$components.uid",
               "type": "$components.type",
               "_id": "$components._id",
               "execution_times": "$components.execution_times",
               "output_samples": {
                   "name": "$components.output_samples.name",
                   "_id": "$components.output_samples._id"
               },
               "input_samples": "$components.input_samples",
               "control_ports": "$components.control_ports"
           }
       }, 
       "output_samples_values": {"$push": "$components.output_samples.values" }
   }},
   { "$project": { 
       "_id": { 
           "_id": "$_id._id", 
           "components": {
               "uid": "$_id.components.uid",
               "type": "$_id.components.type",
               "_id": "$_id.components._id",
               "execution_times": "$_id.components.execution_times",
               "output_samples": {
                   "name": "$_id.components.output_samples.name",
                   "_id": "$_id.components.output_samples._id",
                   "values": "$output_samples_values"
               },
               "input_samples": "$_id.components.input_samples",
               "control_ports": {
                   "name": "$_id.components.control_ports.name",
                   "_id": "$_id.components.control_ports._id"
               }
           }
       }, 
       "control_ports_values": "$_id.components.control_ports.values"
   }},
   { "$unwind": "$control_ports_values" },
   { "$limit": 5 },
   { "$group": { 
       "_id": { 
           "_id": "$_id._id", 
           "components": {
               "uid": "$_id.components.uid",
               "type": "$_id.components.type",
               "_id": "$_id.components._id",
               "execution_times": "$_id.components.execution_times",
               "output_samples": {
                   "name": "$_id.components.output_samples.name",
                   "_id": "$_id.components.output_samples._id",
                   "values": "$_id.components.output_samples.values"
               },
               "input_samples": "$_id.components.input_samples",
               "control_ports": {
                   "name": "$_id.components.control_ports.name",
                   "_id": "$_id.components.control_ports._id"
               }
           }
       }, 
       "control_ports_values": {"$push": "$control_ports_values" }
   }}
])

所有只是以前5个值对两个数组进行切片。

因此,如果您需要嵌套数组,则在检索结果时在代码中执行“切片”。否则,将模式更改为更符合您目的的模式。