使用groovy将包含BasicDBObject的嵌套emded列表更新为mongoDB中的DBRef [英] Updating nested emdedded list containing BasicDBObject to DBRef in mongoDB using groovy

查看:146
本文介绍了使用groovy将包含BasicDBObject的嵌套emded列表更新为mongoDB中的DBRef的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

mongo中文档的结构如下所示:

pre $ Project $(@Entity)
| --Deliverables( @Embedded,在Project内部列表)
| --DeliveryTypes(@Embedded,列表里面的可交付成果)
| --DeliveryItems(DeliveryTypes中的普通列表)
| --log(DeliveryItems中的普通列表)

以及mongo中其他可能的文档结构如下

 项目(@Entity)
| --Deliverables(@Embedded,项目内部列表)
| --DeliveryTypes(@Embedded,list (交付内容中的普通列表)
| - 任务(DeliveryItems中的普通列表)
| --log(任务中的普通列表)
| - 交付内容中的普通列表
| --DeliveryItems --log(在DeliveryItems中的简单列表)

这是Project文档在mongoDB中的样子

  {
_id:Obje ctId(51827f4fe4b07cc5088149ff),
className:Project,
name:TestProject,
description:这是一个测试项目,
state:Open,
dateCreated:ISODate(2013-05-02T14:59:27.069Z),
projectStatuses:[
{
状态:正常,
dateCreated:ISODate(2013-05-02T14:59:27.071Z),
用户:{
_id :testUser@abc.com,
firstName:Test,
lastName:User,
enabled:true,
accountExpired :false,
accountLocked:false,
passwordExpired:false
}
}
],
commercialStatuses:[
{
status:正在跟踪,
dateCreated:ISODate(2013-05-02T14:59:27.074Z),
用户:{
_id:testUser@abc.com,
firstName:Test,
lastName:User,
enabled:true,
accountExpired:false,
accountLocked:false,
passwordExpired:false
}
}
],
交付物:[
{
embeddedId:ObjectId(
name:TestSite 01,
deliveryTypes:[
{
deliveryItems:[
{
embeddedId:ObjectId(5183702fe4b014bf00000003),
type:Plain,
log:[
{
dateCreated:ISODate(2013-05 -03T08:42:10.592Z),
oldValue:打开,
newValue:关闭,
用户:{
_id:testUser@abc.com,
firstName:Test,
lastName:User,
启用:true,
accountExpired:false,
accountLocked:false,
passwordExpired:false
}
},
{
dateCreated:ISODate(2013-05-03T09:24:30.336Z),
oldValue:Closed,
newValue:Open,
用户:{
_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:打开,
newValue:关闭,
用户:{
_id:testUser@abc.com,
firstName:测试,
lastName:用户,
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),
分配用户:测试人员,
description:这是测试子任务
}
],
log:[
{
dateCreated:ISODate(2013-05-03T08:07:52.725Z),
oldValue:打开,
newValue:已关闭,
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和log 

user:DBRef(User,testUser@abc.com)

这是我到目前为止所尝试过的,

  Mongo连接=新的Mongo(localhost,27017 )
DB db = conn ection.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 - >
deliverrable.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会抛出异常can not not cast BasicDBObject to DBRef:/ b / b
$ b

  projects.each {project  - > 
Project.update(['_ id':project._id]){setdeliverables,project.deliverables}
}

我在迁移后检查了数据库,没有用户对象的实例,只有引用,但仍然得到异常。编写迁移脚本并不是很好,所以如果有人能够帮助我保存查询的文档(看起来像一张大地图),那将会很棒,或者指导文档的一些有用链接也会有所帮助。提前致谢:)

解决方案

好的,我终于设法将mongo的BasicBDObject嵌入列表更新为mongo DBRef Object。



首先您应该使用以下代码建立连接。下面的代码连接到本地机器端口27017(默认端口)上的测试数据库。



$ p $ Mongo连接=新Mongo(localhost,27017)
DB db = connection.getDB('test')



接下来写一个查询,获取存储在mongo中的所有文档,需要更新,在我的案例中是所有文档。

  //指定要查询的集合
DBCollection projectCollection = Project。集合
//使用下面的代码指定查询,在我的情况下全部为
//文档,因此我将查询对象留空
QueryBuilder projectQuery = new QueryBuilder()
//指定文档的哪些字段应该被检索,在我的情况下
//我需要所有字段,所以我把它留空
BasicDBObject projectKeys = new BasicDBObject()
//初始化一个游标,它更像是一个迭代器,对于结果
DBCursor projectCursor = projectCollection.find(projectQuery.get(),projectKeys)
//将获得的结果转换为ArrayList $ b $ ArrayList projects = projectCursor.toArray()

遍历结果并更新要更新的内容。

  projects.each {项目 - > 
project.deliverables.each {deliverable - >
deliverrable.deliveryTypes.each {deliveryType - >
deliveryType.deliveryItems.each {deliveryItem - >
deliveryItem.log.each {log - >
updateLogUser(log.user,db)
}
}
}
}
}

static updateLogUser(def user ,DB db){
try {
//user.fetch是检查对象是BasicDBObject
//还是DBRef对象。如果用户对象是BasicDBObject,那么.fetch()
//抛出一个异常,否则它将得到被引用的对象
if(user&& user.fetch()){
return user
} else {
return null
}
} catch(Exception e){
return new DBRef(db,User,user._id)
}
}

现在保存您对文档所做的更改。 / p>

  projects.each {project  - > 
!project.deliverables?:
Project.update(['_ id':project.id]){setdeliverables,project.deliverables}
}

The structure of document in mongo is as follows

Project(@Entity)
  |--Deliverables(@Embedded, list inside Project)
       |--DeliveryTypes(@Embedded, list inside Deliverables)
            |--DeliveryItems(Plain list inside DeliveryTypes)
                 |--log(Plain list inside DeliveryItems)

and the other possible structure of document in mongo is as follows

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)

This is how the Project document looks like in 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
                                         }
                            }
                        ]
                    }
                ]
            }
   ]
}

now the problem I have, I want to change all the occurrences of

"user" : {
          "_id" : "testUser@abc.com",
          "firstName" : "Test",
          "lastName" : "User",
          "enabled" : true,
          "accountExpired" : false,"accountLocked" : false,
          "passwordExpired" : false
         }

under

projectStatuses, commercialStatuses, and log 

to

"user" : DBRef("User", "testUser@abc.com")

This is what I have tried so far,

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)
    }
}

The above code does what I need, but the problem now is how do I save the updated, queried objects? I tried the following but grails keep throwing exception "cannnot cast BasicDBObject to DBRef" when I try to login :/

projects.each { project ->
        Project.update(['_id': project._id]) {set "deliverables", project.deliverables}
    }

I have checked the db after migration and there is no instance of user object, there are only references, but still get the exception. I am not really good with writing migrating scripts, so if someone can help me in how to save queried documents (which looks like a big map), it would be great, or some useful links to how-to documents would also be helpful. Thanks in advance :)

解决方案

okay I have finally managed to update embedded list containing mongo's BasicBDObject to mongo DBRef Object.

first you should establish a connection with the following code. The below code connects to "test" database at port "27017" (default port) on your local machine.

Mongo connection = new Mongo("localhost", 27017)
DB db = connection.getDB('test')

next write a query which gets all the documents stored in mongo, that needs to be updated, in my case all of the documents. The following code helps you do that.

//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()

iterate through the results and update what you want to update

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)
    }
}

and now to save the changes you have made to the document.

projects.each { project ->
   !project.deliverables ?: 
      Project.update(['_id': project.id]) {set "deliverables", project.deliverables}
}

Since you cannot directly update the nested list in mongodb, which is bug in mongo, and is reported to mongo, hopefully they fix it soon, you can update the parent of nested lists, in my case it is the "deliverables" list which is the parent of nested lists

这篇关于使用groovy将包含BasicDBObject的嵌套emded列表更新为mongoDB中的DBRef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆