如何访问/读取嵌套的mongo字段/元素

时间:2018-09-05 00:36:16

标签: mongodb nested

在阅读MongoDB update data in nested field之后,我使用
设置了一个嵌套元素 db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });

如何访问该元素?(只是子元素而不是整个文档)
例如db.users.findOne({_id: '123'}, {'$elem':"friends.0.emails.0.email"});

例如:
如果是JavaScript对象,
db.users["123"].friends[0].emails[0].email
如果是Python字典,那就是
db.users["123"]["friends"][0]["emails"][0]["email"]
如果是Ruby Hash,也应该是
db.users["123"]["friends"][0]["emails"][0]["email"]

理想情况下,答案是一个函数,该函数接受键列表(例如[ "friend", 0, "emails", 0 , "email" ])并返回该嵌套元素的值(例如2222)。

我是计算机科学专业的学生,​​并且是一名全职开发人员:我的同龄人,教授,同事或老板都无法回答这个问题。我正在尝试学习mongo,访问元素是我想学习的第一件事。我花了几天的时间阅读有关$ filter,$ elem,.dot运算符和$运算符的相关堆栈溢出问题和Mongo文档,但是似乎没有什么可以解释如何简单地访问嵌套元素的。

以下是我发现的一些相关问题,不是我要寻找的
MongoDB - how to query for a nested item inside a collection?
^讨论一系列元素(我只想要1个)
MongoDB nested array query
^检查数组数组的成员资格(我只想访问一个elem而不检查成员资格)
Get particular element from mongoDB array
^使用查询进行过滤(颜色=“红色”),但我不想按查询进行过滤,我想检索一个完全唯一的索引(例如,第0个电子邮件)
retrieve a nested document with mgo
^这有点接近,但是用户从未发布过mongo答案,而是引用了go-Lang帖子。它还没有涵盖数组的可能性。

2 个答案:

答案 0 :(得分:0)

如果有人仍然对此感到疑惑,解决方案似乎位于MongoDB Docs

基本语法是:

db.document.find({[YOUR SEARCH PARAMETER HERE]},{[THE FIELD(S) YOU WANT RETURNED HERE]}

在文档中,他们列出了一个示例,因此我在此处将其与SQL等效项一起粘贴了,这应该有助于弄清楚事情。

这是文档集和文档结构:

db.inventory.insertMany( [
  { item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
  { item: "notebook", status: "A",  size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
  { item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
  { item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
  { item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);

这里是从“状态= A”条目中获取字段“ item”和“ status”的查询

db.inventory.find( { status: "A" }, { item: 1, status: 1 } )

SQL等效项是:

SELECT _id, item, status from inventory WHERE status = "A"

将其简化为选择单个条目而不是“状态= A”的所有条目是很简单的。

答案 1 :(得分:0)

两年后,我自己找到了答案。克里斯的答案非常接近,我很欣赏它用一个例子写得很好,但是并没有涵盖嵌套数据的全部内容。

如果您有一个ID为'123'的对象,并且想要获取thatObject.friends[0].emails[0].email
,请运行以下命令:

// NOTE this string method does work for EVERY case (see explanation below) 
object = db.document.findOne({ _id: '123' }, {projection:{ "friends.0.emails.0.email": 1 }})
// DONT actually use eval, see `get` from `good-js` on npm for an example of non-eval retrieval
return eval("object.friends.0.emails.0.email")

这对我来说并不直观,因为有$set,所以我一直在寻找$get。但是,大多数时候,人们希望获得的不仅仅是一件事情,这就是MongoDB有预测的原因。上面的示例使用正投影(1表示:仅包含此),但也可以使用负投影(使用0表示:获得除此东西以外的所有内容)。

我的字符串“ friends.0.emails.0.email”问题

我通常不会接受这种回答:如果thatObject.friends[0]thatObject["friends.txt"][0]这样的话怎么办? (这是一个完全有效的JSON / Javascript密钥。)这将导致"friends.txt.0.emails.0.email"损坏!
事实证明,

  1. 在MongoDB密钥中根本不允许使用句点
  2. 也不允许以$开头的密钥
  3. 允许使用UTF-8中的所有其他内容

这会导致一些看起来很奇怪的查询
"i am a key with spaces.im a key as well: ))(@U%@#%(*%)*%#^_%#*@$_"
这是两个有效的键,中间用句点隔开,令我不舒服的是,您可以像平常一样检索它们。