MongoDB 查询 - 返回切片数组

Posted

技术标签:

【中文标题】MongoDB 查询 - 返回切片数组【英文标题】:MongoDB query - Return sliced arrays 【发布时间】:2014-04-22 14:35:24 【问题描述】:

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

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:

所以这确实带来了问题,“你真的是想拥有数组”吗?之所以这么说,是因为随着信息的呈现,实际上数组的唯一部分似乎是“值”字段。

我想数据比您想象的要复杂一些。组件数组可以保存任意数量的具有唯一“uid”的组件,每个“执行”都可能不同。因此,我想我肯定必须为组件使用数组。

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

数组中特定组件的位置是我不知道的唯一索引,因为数据创建应用程序会在值更新之前初始化执行。因此,我只需要一个“位置 $ 运算符”。它应该类似于 "components.$.output_samples.0.values": "$slice": 5

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

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

非常感谢您的详细回答。

【问题讨论】:

显示您的数据和预期结果可能会有所帮助。 这不会改变给出的答案的上下文,尽管使用引用进行了编辑。你想做的事是做不到的。或者您是否试图通过编辑您的问题来回复?你的问题仍然有点不清楚,但如果我明白你的意思,你希望从位置x 开始并在位置y 结束。这是一个比您最初提出的问题要复杂得多的问题。重新考虑答案。那里有很好的信息让你重新思考那个附加问题。 我没有尝试回答我自己的问题。相反,我试图澄清我的问题。实际上,我想通过从位置 x 开始并在位置 y 结束来对这些数组进行切片。我只是感到惊讶,因为在客户端获取整个数据集并使用 javascript 对其进行切片不会有任何问题。不知何故,这感觉像是一个基本的操作。这就是为什么我不明白为什么它不能在查询中轻松完成。对不起,但不知怎的,我想我不明白你的意思。是什么让它变得困难?我不知道数组中只有一个位置。剩下的只是一个“限制” 那么“限制”就是重点。仅仅因为 your 结构只有 singular 元素并不能使您期望以任意方式进行投影。对于一个真正“过于宽泛”的主题,这里给出了很多详细的答案。所以结果是这样的。你不能做你正在尝试的事情。那是没有真的“跳过箍”来尝试得到这个结果。用代码来做。答案解释了这一点。您不可能有那么多数据要检索。 16MB BSON 限制。编码简单。 【参考方案1】:

$slice 或任何类型的数组投影都会遇到的问题是,您将数组嵌套在您定义的模式中。我还注意到positional $ 运算符的使用偷偷溜进去偷看,所以最好在文档的上下文中从那里进行解释。

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

$ 投影运算符将字段的内容限制为与查询文档匹配的 first 元素。 字段必须出现在查询文档中

因此,对于初学者来说,您并不是在查询中要求匹配任何数组的任何元素中的特定字段。仅凭这一点,就无法对匹配的元素进行投影。在任何情况下,即使您这样做了,也只有 第一个 匹配的数组元素可以可能匹配。

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

$slice 在这种情况下的问题在于,您实际上不知道 "which" 嵌套之外的数组元素要对其进行操作。因此,您呈现的样式将不起作用,因为元素可能是 any 可能的索引。正确的形式,如果它被支持,并且它是,应该是这样的:

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

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

所以这确实带来了疑问,“你真的意思是拥有数组”吗?之所以这么说,是因为随着信息的呈现,实际上数组的唯一部分似乎是 "values" 字段。

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

考虑到所有嵌套的“其他”数组只有只有一个一个元素。所以它使这成为可能,但不切实际

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 个值切片。

因此,如果您需要嵌套数组,请在检索结果时在代码中进行“切片”。否则,将架构更改为更实际适合您目的的架构。

【讨论】:

以上是关于MongoDB 查询 - 返回切片数组的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB 记录所有查询

MongoDB状态查询:db.serverStatus()

MongoDB查询在过滤数组后根据数组大小返回所有内容?

mongoDB配置

Mongodb 使用查询生成器返回空数组

查询一个对象数组并返回一个对象 - mongodb