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 查询 - 返回切片数组的主要内容,如果未能解决你的问题,请参考以下文章