MongoDB-查询嵌入式文档数组



我最近开始使用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
}

因此,我的问题是,是否有可能查询数据库并只返回"数据"数组中所需的元素和时间戳,或者我需要在读取数据库后重新创建响应JSON对象。

致以亲切的问候。

欢迎来到mongo世界。您可以通过聚合轻松实现这一点

  • $uwnind来解构数组
  • $match获取期望值
  • $addFields向对象添加新字段
  • $replaceRoot使对象成为根

这是代码

db.collection.aggregate([
{ "$unwind": "$data" },
{ "$match": { "data.id": "data_1" } },
{ "$addFields": { "data.timestamp": "$timestamp" } },
{ "$replaceRoot": { "newRoot": "$data" } }
])

正在工作的Mongo游乐场

尽管@varman的答案对这个问题是正确的,但为了更好地匹配我的情况,即数组data将有很多元素(超过100个(,因为注释"展开"中的@varman可能会很昂贵,特别是当数组包含大量元素时。因此,在理想的情况下,当数组只包含不需要的元素时,我更喜欢进行"展开",以实现这一点,我将顺序更改为:

  • 使用"$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

最新更新