關系型數據庫中,表與表的關聯關系有1:1,也有1:n的。在java的面向對象的世界里就是主對象嵌子對象,與主對象嵌集合<子對象>的兩種形式。
主對象嵌子對象操作:
新增、修改都直接用如下方法:
mongoTemplate.updateFirst(new Query(criteria), update, clazz, collectionName);
刪除:(刪除內嵌對象列即可)
update.unset(columnName + ".$");
WriteResult updateFirst = mongoTemplate.updateFirst(query, update, clazz, collectionName);
主對象嵌集合<子對象>的操作:
java對象的例子:
{ "_id" : "195861", "tags" : [ { "tagId" : NumberLong(766), "optDate" : ISODate("2013-08-12T15:21:02.930Z"), "enable" : true }, { "tagId" : NumberLong(778), "optDate" : ISODate("2013-08-12T15:21:02.930Z"), "enable" : true } ] }
MongoTemplate操作的示例:
/** **給tags數組添加一個元素 */ @Override public Response<Integer> addTag(String id, Long tagId) { try { Tag tag = new Tag(tagId); tag.setOptDate(new Date()); tag.setEnable(true); Query query = Query.query(Criteria.where("_id").is(id)); Update update = new Update(); update.addToSet("tags", tag); mongoTemplate.upsert(query, update, User.class); } catch (Exception e) { return new Response<Integer>(0); } return new Response<Integer>(1); } /** **修改tags數組中內嵌文檔指定一個元素的值 */ @Override public Response<Integer> disableTag(String id, Long tagId) { try { Query query = Query.query(Criteria.where("_id").is(id) .and("tags.tagId").is(tagId)); Update update = new Update(); update.set("tags.$.enable", false); mongoTemplate.updateFirst(query, update, User.class); } catch (Exception e) { return new Response<Integer>(0); } return new Response<Integer>(1); } /** **刪除tags數組中指定的內嵌文檔 */ @Override public Response<Integer> removeTag(String id, Long tagId) { try { Query query = Query.query(Criteria.where("_id").is(id) .and("tags.tagId").is(tagId)); Update update = new Update(); update.unset("tags.$"); mongoTemplate.updateFirst(query, update, User.class); } catch (Exception e) { return new Response<Integer>(0); } return new Response<Integer>(1); }
update.unset這種方法有一個缺陷,會將符合條件的數據修改成null,如果要徹底刪除,則需要使用pull(pull刪除內嵌文檔的時候,student對象的值一定要和被刪除的一模一樣(不懂))
Query query = Query.query(Criteria.where("classId").is("1")); Update update = new Update(); Student student = new Student("2","lisi",18,"man"); update.pull("Students",student); mongoTemplate.updateFirst(query, update, "class");
pull方式刪除內嵌文檔中的行:
Query query = Query.query(Criteria.where("_id").is(id)); BasicDBObject s = new BasicDBObject(); s.put("tagId", tagid); Update update = new Update(); update.pull("tags", s); mongoTemplate.updateFirst(query, update, User.class);
嵌套對象的查詢:
這里需要注意下,如果返回的數據列表是整個對象(外對象+內嵌對象)時,內嵌對象的所有行都會被返回,只有返回值對象指定為內嵌對象時,才能過濾掉內嵌對象集合中不符合條件的記錄。
db.getCollection('tz_member').find({"memberPhotos.memberId":'4'},{"memberPhotos.$":1}).pretty();
db.getCollection('tz_member').find({"member_id":"3","memberPhotos.memberId":{'$in':['4']}},{"memberPhotos.$":1}).pretty();
內嵌文檔的主鍵問題
MongoDB CRUD操作(insert
,update
,find
,remove
)所有的操作都只在頂級文檔上進行--當然,可以按嵌入文檔中的字段進行篩選。嵌入文檔總是在父文檔中返回。
_id
字段是父文檔的必需字段,通常在嵌入文檔中不需要或不存在。如果需要唯一標識符,當然可以創建它們,並且可以使用_id
字段來存儲它們,如果這對代碼或心智模型來說是方便的話;更典型的是,它們是以它們所代表的名稱命名的(例如“用戶名”、“其他SystemKey”等等)。MongoDB本身和任何驅動程序都不會自動填充_id
字段,但頂層文檔除外。
特別是在Java中,如果希望為_id
在嵌入式文檔中,可以使用以下方法來完成:
someEmbeddedDoc._id = new ObjectId();