在mongodb中经常遇到这样的数据结构:
{
"_id" : ObjectId("5cd01dfc5d157b5d9bc2750a"),
"results" : [
{
_id:"5cd01dfc5d157b5d9bc27597"
name:"one",
"relation_kpi_draft" : [
{
"parent_id" : null,
"kpi_id" : ObjectId("5cd01dfc5d157b5d9bc2750b"),
"kpi_name" : null,
"is_deleted" : 0,
"_id" : ObjectId("5cd01dfc5d157b5d9bc2750d")
},
{
"parent_id" : null,
"kpi_id" : ObjectId("5cd01dfc5d157b5d9bc2752b"),
"kpi_name" : null,
"is_deleted" : 0,
"_id" : ObjectId("5cd01dfc5d157b5d9bc2751d")
},
]
},
{
_id:"5cd01dfc5d157b5d9bc2757c"
name:"two",
"relation_kpi_draft" : [
{
"parent_id" : null,
"kpi_id" : ObjectId("5cd01dfc5d157b5d9bc2750b"),
"kpi_name" : null,
"is_deleted" : 0,
"_id" : ObjectId("5cd01dfc5d157b5d9bc2750d")
},
{
"parent_id" : null,
"kpi_id" : ObjectId("5cd01dfc5d157b5d9bc2752b"),
"kpi_name" : null,
"is_deleted" : 0,
"_id" : ObjectId("5cd01dfc5d157b5d9bc2751d")
},
]
}
]
}
1.查询
当想查询name=“one"的值时可以直接使用"results.name”:"one"或者results:{$eleMatch:{name:“one”}}等的方式查询
2.修改
需求1:
将results._id为“5cd01dfc5d157b5d9bc27597”文档中的name字段更改为one-update
此时我们可以直接使用mongodb中的$占位符,当我们指定条件后,占位符会自动定位到该字段进行操作
db.集合名称.update(
{"results._id":ObjectId("5cd01dfc5d157b5d9bc27597")},
{$set:{"results.$.name":"one-update"}})
需求2:
将results._id为“5cd01dfc5d157b5d9bc27597”文档中的
relation_kpi_draft数组中的_id为"5cd01dfc5d157b5d9bc2750d"的kpi_name修改为null-update,
此时我们发现,使用多个$占位符会出现错误无法满足我们的需求,因为目前mongodb中的占位符只支持一个,社区也没有什么特别好的改进方法,但mongodb有一个特性,它是文档型数据库,也就是说,可以采用数组+下标的形式进行操作
栗子:results.$.relation_kpi_draft.0(下标).kpi_name:“one-update”
那么问题又来了,我们如何去获取这个下标呢,当然是要先进行查询了,这个时候建议大家可以封装一个用于获取这种内嵌文档属性下标方法,提高代码重用度,减少冗余
当我们查询出该文档并进行条件循环遍历时,便可以得到results._id为“5cd01dfc5d157b5d9bc27597”且relation_kpi_draft._id为“5cd01dfc5d157b5d9bc2750d”的属性下标,得到下标,我们就可以直接精准的进行更新操作了
db.集合名称.update(
{"results._id":ObjectId("5cd01dfc5d157b5d9bc27597")},
{$set:{results.$.relation_kpi_draft.0.kpi_name:"one-update"}})
这种下标形式的方法是最笨也是最终的办法,所以在设计表结构的时候,尽量不要设置这种嵌套过深的文档,那样会增加操作的复杂度
3.添加
需求1:
在results._id为“5cd01dfc5d157b5d9bc27597”文档中的relation_kpi_draft数组文档再添加一个json
这个很简单,直接使用$占位符就能解决问题
db.集合名称.update(
{"results._id":ObjectId("5cd01dfc5d157b5d9bc27597")},
{$push:{results.$.relation_kpi_draft:
{
"parent_id" : null,
"kpi_id" : ObjectId("5cd01dfc5d157b5d9bc2752t"),
"kpi_name" : null,
"is_deleted" : 0,
"_id" : ObjectId("5cd01dfc5d157b5d9bc2751h")
}
}})
4.删除
分为真删除和假删除,
假删除就是更改一个状态字段,和使用数组下标的方式同理,在这里就不多做阐述。
但真删除,我们使用$pull进行操作,同样是使用占位符,当然,如果嵌套太深,也只能使用数组下标的形式进行操作
需求:
在results._id为“5cd01dfc5d157b5d9bc27597”文档中的relation_kpi_draft数组文档中_id为“5cd01dfc5d157b5d9bc2750d”的文档删除
db.集合名称.update(
{"results._id":ObjectId("5cd01dfc5d157b5d9bc27597")},
{$pull:{results.$.relation_kpi_draft:{_id:ObjectId("5cd01dfc5d157b5d9bc2750d")}}})
//删除多个的时候可以使用$in:[]
至此,如果理解这些,那么基本的增删改查类的操作就没有问题了