我试图在以下模式上指定一个特定的查询:
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
字段可以包含数百万个值。甚至更多。这就是为什么我想收集用户需要的尽可能多的值。
非常感谢您详细的答复。
您将在这里使用$slice
或任何类型的数组投影的问题是您在已定义的模式中嵌套数组的事实。我还注意到这里使用了位置$
操作符,所以最好从这里的文档上下文中进行解释。
在那一页上有这个:
因此,对于初学者来说,您不需要在查询中要求在任何数组的任何元素中匹配特定字段。仅凭这一点,就无法对匹配的元素进行投影。在任何情况下,只有第一个匹配的数组元素才有可能匹配,即使这样做了。
- $ projection运算符将字段的内容限制为第一个与查询文档匹配的元素。
- 字段必须在查询文档
中出现
在你的结构中,唯一可以匹配的是数组"components"的顶部位置。
$slice
在这种情况下的问题是,您实际上不知道"哪个"数组元素在嵌套之外进行操作。因此,您所呈现的样式将不起作用,因为元素可以是和任何可能的索引。如果支持,而不是,那么正确的格式应该是:
{ "components.0.output_samples.0.values": { "$slice": 5 } }
因为你需要指定索引路径到你实际谈论的元素。
所以这确实带来了一个问题,"你真的意味着有数组吗?"之所以这么说,是因为当信息呈现时,似乎实际上唯一的部分是"值"字段。嵌套列表将成为各种事情的问题,并且对于更新来说是出了名的糟糕。在可能的情况下,你应该考虑其他选择。在这种情况下,如果您想限制输出,那么唯一实际的方法是检索整个文档,然后用代码处理数组以限制返回的结果。
考虑到所有嵌套仅的"other"数组只有一个元素,即使下面的"非常复杂"咒语也只能("有点")以它当前的形式起作用。所以这是可能的,但是不切实际的: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个值切片两个数组
因此,如果您需要嵌套数组,那么在检索结果时在代码中进行"切片"。否则,将模式更改为更实际地适合您的目的。