我最近开始使用MongoDB来保存一个项目的数据,基本思路如下。
在服务器端,我在 WebSocket 上接收一些 JSON 对象并将其存储在数据库中。
我收到的数据如下所示:
{
{ident: "message_1"},
data:
[
{id: "data_1", value : 10},
{id: "data_2", value : 20},
{id: "data_3", value : 40},
{id: "data_4", value : 60},
{id: "data_4", value : 60},
],
timestamp : 12234456
}
我目前正在数据库中保存整个 JSON 对象。
服务器还应该处理用户 http 请求,它在数据库中查询请求的数据。用户请求总是针对 data
数组的一个元素和时间戳。因此,服务器响应应如下所示:
{ id: "data_1", value : 10, timestamp : 12234456}
我尝试将 db.collection.find 与 $elemMatch 一起使用,但我的输出仍然包含 data
数组和所需的元素。
{
data:
[{
id: "data_1",
value: 10
}],
timestamp : 12234456
}
所以我的问题是是否有可能查询数据库并仅返回“data”数组的所需元素以及时间戳,否则我需要在读取数据库后重新创建响应 JSON 对象。
亲切的问候。
答案 0 :(得分:2)
欢迎来到蒙戈世界。您可以通过聚合轻松实现这一点
$uwnind
解构数组$match
获取期望值$addFields
向对象添加新字段$replaceRoot
使对象成为根这是代码
db.collection.aggregate([
{ "$unwind": "$data" },
{ "$match": { "data.id": "data_1" } },
{ "$addFields": { "data.timestamp": "$timestamp" } },
{ "$replaceRoot": { "newRoot": "$data" } }
])
答案 1 :(得分:0)
虽然@varman 的回答对这个问题是正确的,但为了更好地匹配我的情况,数组 data
将有很多元素(超过 100),因为@varman 在评论“unwind”中可能特别昂贵当数组包含大量元素时。因此,理想情况下,当数组仅包含所需元素时,我更愿意执行“展开”,以实现我将订单更改为以下内容:
"$match
仅获取具有所需 data
元素的文档{ "$match": { "data.id": "data_1" } }
$project
和 $filter
从数据中过滤掉不需要的元素 $project: {
data: {
$filter: {
input: "$data",
as: "data",
cond: {$eq: ["$$data.id", "data_1"]}
}
},
"timestamp": 1,
"_id": 0
}
timestamp
字段 { $addFields: {"data.timestamp": "$timestamp"} }
unwind
从输入文档中解构data
数组字段,为每个元素输出一个文档。 {
$unwind: "$data"
}
$replaceRoot
将输入文档替换为 data
字段。{"$replaceRoot": {"newRoot": "$data"}}
希望这对需要做同样事情的任何人都有用,如果您对我当前的设置有任何建议/改进,请我来寻求建议,因为我是 MongoDB 的新手。
运行示例 Mongo Playground