蒙古语文档结构如下
Project(@Entity)
|--Deliverables(@Embedded, list inside Project)
|--DeliveryTypes(@Embedded, list inside Deliverables)
|--DeliveryItems(Plain list inside DeliveryTypes)
|--log(Plain list inside DeliveryItems)
和mongo中其他可能的文档结构如下
Project(@Entity)
|--Deliverables(@Embedded, list inside Project)
|--DeliveryTypes(@Embedded, list inside Deliverables)
|--DeliveryItems(Plain list inside DeliveryTypes)
|--Tasks(Plain list inside DeliveryItems)
|--log(Plain list inside Tasks)
|--log(Plain list inside DeliveryItems)
这是项目文档在mongoDB中的样子
{
"_id" : ObjectId("51827f4fe4b07cc5088149ff"),
"className" : "Project",
"name" : "TestProject",
"description" : "This is a test project",
"state" : "Open",
"dateCreated" : ISODate("2013-05-02T14:59:27.069Z"),
"projectStatuses" : [
{
"status" : "On Track",
"dateCreated" : ISODate("2013-05-02T14:59:27.071Z"),
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
}
],
"commercialStatuses" : [
{
"status" : "On Track",
"dateCreated" : ISODate("2013-05-02T14:59:27.074Z"),
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
}
],
"deliverables" : [
{
"embeddedId" : ObjectId("5183702fe4b014bfbe387d37"),
"name" : "TestSite 01",
"deliveryTypes" : [
{
"deliveryItems" : [
{
"embeddedId" : ObjectId("5183702fe4b014bf00000003"),
"type" : "Plain",
"log" : [
{
"dateCreated" : ISODate("2013-05-03T08:42:10.592Z"),
"oldValue" : "Open",
"newValue" : "Closed",
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
},
{
"dateCreated" : ISODate("2013-05-03T09:24:30.336Z"),
"oldValue" : "Closed",
"newValue" : "Open",
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
},
{
"dateCreated" : ISODate("2013-05-03T13:33:06.550Z"),
"oldValue" : "Open",
"newValue" : "Closed",
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
}
]
},
{
"embeddedId" : ObjectId("5183702fe4b014bf00000004"),
"type" : "task",
"tasks" : [
{
"embeddedId" : ObjectId("518370abe4b014bf00000001"),
"name" : "TestSubTask 1",
"log" : [
{
"dateCreated" : ISODate("2013-05-03T08:09:15.624Z"),
"oldValue" : "Open",
"newValue" : "Created",
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
}
],
"plannedEndDate" : ISODate("2013-05-02T22:00:00Z"),
"assignedUser" : "Test person",
"description" : "This is a test sub task"
}
],
"log" : [
{
"dateCreated" : ISODate("2013-05-03T08:07:52.725Z"),
"oldValue" : "Open",
"newValue" : "Closed",
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,
"accountLocked" : false,
"passwordExpired" : false
}
}
]
}
]
}
]
}
现在的问题是,我想改变所有出现的
"user" : {
"_id" : "testUser@abc.com",
"firstName" : "Test",
"lastName" : "User",
"enabled" : true,
"accountExpired" : false,"accountLocked" : false,
"passwordExpired" : false
}
下projectStatuses, commercialStatuses, and log
"user" : DBRef("User", "testUser@abc.com")
这是我到目前为止所尝试的,
Mongo connection = new Mongo("localhost", 27017)
DB db = connection.getDB('test')
DBCollection projectCollection = Project.collection
QueryBuilder projectQuery = new QueryBuilder()
BasicDBObject projectKeys = new BasicDBObject()
DBCursor projectCursor = projectCollection.find(projectQuery.get(), projectKeys)
ArrayList projects = projectCursor.toArray()
projects.each { project ->
project.deliverables.each { deliverable ->
deliverable.deliveryTypes.each { deliveryType ->
deliveryType.deliveryItems.each { deliveryItem ->
deliveryItem.log.each { log ->
updateLogUser(log, db)
}
}
}
}
}
static updateLogUser(def log, DB db) {
if (log.user?._id) {
log.user = new DBRef(db, "User", log.user?._id)
}
}
上面的代码做了我需要的,但现在的问题是我如何保存更新,查询对象?我尝试了以下操作,但当我尝试登录时,grails一直抛出异常" cannot cast BasicDBObject to DBRef":/
projects.each { project ->
Project.update(['_id': project._id]) {set "deliverables", project.deliverables}
}
我已经检查了迁移后的db,没有用户对象的实例,只有引用,但仍然得到异常。我不太擅长编写迁移脚本,所以如果有人能帮助我如何保存查询的文档(看起来像一个大地图),那就太好了,或者一些有用的指南文档链接也会很有帮助。提前感谢:)
好的,我终于设法更新嵌入列表包含mongo的BasicBDObject到mongo DBRef Object。
首先应该用下面的代码建立一个连接。下面的代码在本地机器的端口"27017"(默认端口)连接到"test"数据库。
Mongo connection = new Mongo("localhost", 27017)
DB db = connection.getDB('test')
接下来写一个查询,获取存储在mongo中的所有文档,需要更新,在我的例子中是所有文档。下面的代码可以帮助您做到这一点。
//specify which collection you want to query
DBCollection projectCollection = Project.collection
//specify the query using the following code, in my case all
//documents so I leave the query object empty
QueryBuilder projectQuery = new QueryBuilder()
//specify what fields of the document should be retrieved, in my case
//I need all the fields, so I leave it empty
BasicDBObject projectKeys = new BasicDBObject()
//initialize a cursor, it is more like an iterator, to the results
DBCursor projectCursor = projectCollection.find(projectQuery.get(), projectKeys)
//convert the obtained results to an ArrayList
ArrayList projects = projectCursor.toArray()
遍历结果并更新您想要更新的
projects.each { project ->
project.deliverables.each { deliverable ->
deliverable.deliveryTypes.each { deliveryType ->
deliveryType.deliveryItems.each { deliveryItem ->
deliveryItem.log.each { log ->
updateLogUser(log.user, db)
}
}
}
}
}
static updateLogUser(def user, DB db) {
try {
//user.fetch is to check whether the object is BasicDBObject
//or DBRef object. if user object is a BasicDBObject then .fetch()
//throws an exception else it gets the referenced object
if (user && user.fetch()) {
return user
} else {
return null
}
} catch (Exception e) {
return new DBRef(db, "User", user._id)
}
}
,现在保存您对文档所做的更改。
projects.each { project ->
!project.deliverables ?:
Project.update(['_id': project.id]) {set "deliverables", project.deliverables}
}
因为你不能直接更新mongodb的嵌套列表,这是mongo的错误,并报告给mongo,希望他们很快修复它,你可以更新嵌套列表的父,在我的情况下,它是"可交付成果"列表,这是嵌套列表的父