Mongdb中存储数据关系--------1对多关系
来源:互联网 发布:56相册制作软件 编辑:程序博客网 时间:2024/06/10 05:37
每次写技术分享文章太无聊,为了给自己不无聊,讲个子之鱼安之鱼之乐的典故,故事来自<庄子秋水>:
庄子与惠子游于濠梁之上。
庄子曰:“儵(读音tiao二声,鲦)鱼出游从容,是鱼之乐也。”
惠子曰:“子非鱼,安知鱼之乐?”
庄子曰:“子非我,安知我不知鱼之乐?”
惠子曰:“我非子,固不知之矣;子固非鱼也,子之不知鱼之乐,全矣。”
庄子曰:“请循其本。子曰‘汝安知鱼之乐’云者,既已知吾知之而问我,我知之濠上也。”
以前不喜欢文言文,现在长大了,见识多了,读的书也多了,才发现古文其实没有那么多废话,简洁的话语,蕴藏了很多哲理。
接下来回到Mongdb中的一种常见关系中来。
MongoDB表中------关系型数据库中的1对多关系
应用场景细化:在1对多的关系中,这个多究竟代表多少了?可能是几个,也可能是几万个,甚至是几E个。以下分为3个部分来讲解:
a.n代表很少的部分
比如在person和address中,一个人物对应多个地址,我们采用嵌入式文档来建模。数据格式如下所示:
用json数据表示就是:
{ "_id" : ObjectId("55da8c55e81f2e32285cbf4f"), "_class" : "com.lgy.model.Person", "name" : "feng", "age" : 21, "addresss" : [{ "street" : "武汉 0", "tel" : 111 }, { "street" : "武汉 1", "tel" : 112 }, { "street" : "武汉 2", "tel" : 113 }, { "street" : "武汉 3", "tel" : 114 }, { "street" : "武汉 4", "tel" : 115 }]}*上面的table表用的是MongDB的一个Client图形管理化工具,里面有Tree view , Table view Text view,体验相当不错!
用java实现的原理如下:
Model层代码:
package com.lgy.model;import java.io.Serializable;import java.util.List;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.DBRef;import org.springframework.data.mongodb.core.mapping.Document;import org.springframework.data.mongodb.core.mapping.Field;@Document(collection="person")public class Person implements Serializable {private static final long serialVersionUID = -4477575782622566016L;@Idprivate String Id;private String name;private Integer age;private List<Address> addresss;public String getId() {return Id;}public void setId(String id) {Id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public List<Address> getAddresss() {return addresss;}public void setAddresss(List<Address> addresss) {this.addresss = addresss;}}package com.lgy.model;import java.io.Serializable;public class Address implements Serializable {private static final long serialVersionUID = -6403164299535570346L;private String street;private Integer tel;public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public Integer getTel() {return tel;}public void setTel(Integer tel) {this.tel = tel;}}
dao层代码:
package com.lgy.dao;import com.lgy.base.IBaseDao;import com.lgy.model.Person;public interface IPersonDao extends IBaseDao<Person> {}package com.lgy.dao;import org.springframework.stereotype.Repository;import com.lgy.base.BaseDaoImpl;import com.lgy.model.Person;@Repositorypublic class PersonDaoImpl extends BaseDaoImpl<Person> implements IPersonDao {}封装的IBaseDao和BaseDaoImpl在文章末尾给出。
测试类代码如下:
@Testpublic void insert1Test() {List<Address> addresss = new ArrayList<Address>();for (int i = 0; i < 5; i++) {Address address = new Address();address.setStreet("武汉 " + i);address.setTel(111 + i);addresss.add(address);}Person p = new Person();p.setName("feng");p.setAge(21);p.setAddresss(addresss);personDao.save(p );}
优势:不需要执行单独的查询就可以获得某个Person下对应的所有Address信息
缺点:无法独立操作Address信息,必须先查询到Person文档湖,才有可能继续操作Address。
b.n代表好些个的部分
比如在产品和零部件中,每个产品会有很多个零部件。我们可以才有引用方式来建模。 数据格式如下所示:
{ "_id" : ObjectId("55da9787e81fa872622983ea"), "_class" : "com.lgy.model.Product", "name" : "麦克维", "parts" : ["55da9787e81fa872622983e5", "55da9787e81fa872622983e6", "55da9787e81fa872622983e7", "55da9787e81fa872622983e8", "55da9787e81fa872622983e9"]}/* 0 */{ "_id" : ObjectId("55da9787e81fa872622983e5"), "_class" : "com.lgy.model.Part", "name" : "haha0", "cost" : 45.0}/* 1 */{ "_id" : ObjectId("55da9787e81fa872622983e6"), "_class" : "com.lgy.model.Part", "name" : "haha1", "cost" : 46.0}/* 2 */{ "_id" : ObjectId("55da9787e81fa872622983e7"), "_class" : "com.lgy.model.Part", "name" : "haha2", "cost" : 47.0}/* 3 */{ "_id" : ObjectId("55da9787e81fa872622983e8"), "_class" : "com.lgy.model.Part", "name" : "haha3", "cost" : 48.0}/* 4 */{ "_id" : ObjectId("55da9787e81fa872622983e9"), "_class" : "com.lgy.model.Part", "name" : "haha4", "cost" : 49.0}
java代码实现:
model层代码:
package com.lgy.model;import java.io.Serializable;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;@Document(collection="part")public class Part implements Serializable {private static final long serialVersionUID = 4858632495675595186L;@Idprivate String id;private String name;private Double cost;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getCost() {return cost;}public void setCost(Double cost) {this.cost = cost;}}package com.lgy.model;import java.io.Serializable;import java.util.List;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;@Document(collection="product")public class Product implements Serializable {private static final long serialVersionUID = 5316002024895759481L;@Idprivate String id;private String name;private List<String> parts;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<String> getParts() {return parts;}public void setParts(List<String> parts) {this.parts = parts;}}
dao层代码:
package com.lgy.dao;import com.lgy.base.IBaseDao;import com.lgy.model.Address;import com.lgy.model.Person;import com.lgy.model.Product;public interface IProductDao extends IBaseDao<Product> {}package com.lgy.dao;import org.springframework.stereotype.Repository;import com.lgy.base.BaseDaoImpl;import com.lgy.model.Address;import com.lgy.model.Product;@Repositorypublic class ProductDaoImpl extends BaseDaoImpl<Product> implements IProductDao {}package com.lgy.dao;import com.lgy.base.IBaseDao;import com.lgy.model.Part;public interface IPartDao extends IBaseDao<Part> {}package com.lgy.dao;import org.springframework.stereotype.Repository;import com.lgy.base.BaseDaoImpl;import com.lgy.model.Part;@Repositorypublic class PartDaoImpl extends BaseDaoImpl<Part> implements IPartDao {}
测试代码如下:
@Testpublic void insert2Test() {Product product = new Product();List<String> parts = new ArrayList<String>();product.setName("麦克维");for (int i = 0; i < 5 ; i++) {Part part = new Part();part.setName("haha" + i);part.setCost(45D+ i);partDao.save(part);parts.add(part.getId());}product.setParts(parts);productDao.save(product);}优势:部件作为独立文档存在,可以对某一部件进行独立的操作,比如查看和跟新。
缺点:必须通过2次查询才能找到某个产品的部件信息。
c.n代表很多个部分的时候
比如,每一个机器(host)会产生很大数量的日志信息(logmsg)。在这种情况下,如果你采用嵌入式建模,则一个host文档会非常庞大,从而轻易超过MongoDB的文档大小限制,所以不可行。如果你采用第二中方式建模,用数组来存放所有logmsg的_id值,这种方式同样不可行,因为当日止很多时,即使单单引用objectId也会轻易超过文档大小限制。所以此时,我们采用以下方式,数据格式如下:
/* 0 */{ "_id" : ObjectId("55dabfcae81f0c2821d2ccb6"), "_class" : "com.lgy.model.Host", "name" : "feng", "ip" : "192.168.6.69"}-------------------------------------------------/* 0 */{ "_id" : ObjectId("55dabfcae81f0c2821d2ccb7"), "_class" : "com.lgy.model.Log", "msg" : "这个IP有异常", "hostId" : "55dabfcae81f0c2821d2ccb6"}/* 1 */{ "_id" : ObjectId("55dabfcae81f0c2821d2ccb8"), "_class" : "com.lgy.model.Log", "msg" : "这个IP挂了", "hostId" : "55dabfcae81f0c2821d2ccb6"}
java代码实现方式如下:
model层代码:
package com.lgy.model;import java.io.Serializable;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;@Document(collection="host")public class Host implements Serializable {private static final long serialVersionUID = 4858632495675595186L;@Idprivate String id;private String name;private String ip;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}}package com.lgy.model;import java.io.Serializable;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;@Document(collection="log")public class Log implements Serializable {private static final long serialVersionUID = -3445931472378980445L;@Idprivate String id;private String msg;private String hostId;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getHostId() {return hostId;}public void setHostId(String hostId) {this.hostId = hostId;}}
dao层代码:
package com.lgy.dao;import com.lgy.base.IBaseDao;import com.lgy.model.Host;public interface IHostDao extends IBaseDao<Host> {}package com.lgy.dao;import org.springframework.stereotype.Repository;import com.lgy.base.BaseDaoImpl;import com.lgy.model.Host;@Repositorypublic class HostDaoImpl extends BaseDaoImpl<Host> implements IHostDao {}package com.lgy.dao;import com.lgy.base.IBaseDao;import com.lgy.model.Log;public interface ILogDao extends IBaseDao<Log> {}package com.lgy.dao;import org.springframework.stereotype.Repository;import com.lgy.base.BaseDaoImpl;import com.lgy.model.Log;@Repositorypublic class LogDaoImpl extends BaseDaoImpl<Log> implements ILogDao {}
测试代码如下:
@Testpublic void insert3Test() {Host host = new Host();host.setName("feng");host.setIp("192.168.6.69");hostDao.save(host);Log log1 = new Log();log1.setHostId(host.getId());log1.setMsg("这个IP有异常");logDao.save(log1);Log log2 = new Log();log2.setHostId(host.getId());log2.setMsg("这个IP挂了");logDao.save(log2);}我们在log中,存放对host的_id引用即可。
在1对n的关系中,总结如下:
(1)在数据量很少的情况下,采用嵌入式文档方式来进行建立关联关系;
(2)在数据量比较多的情况下,采用引用方式来建模,在1的那一方,引用多个文档的id
(3)在数据量特别多的情况下,采用引用方式来建模,在多的那一方,引用关联的文档id
*封装的IBaseDao和BaseDaoIpml代码如下:
package com.lgy.base;import java.util.List;import org.springframework.data.mongodb.core.query.Query;import org.springframework.data.mongodb.core.query.Update;public interface IBaseDao<T> {public void save(T t) ; public T findOneById(Object id);public List<T> findAll();public void deleteByModel(T t);public void deleteByQuery(Query query);public void update(Query query, Update update);}package com.lgy.base;import java.lang.reflect.ParameterizedType;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.mongodb.core.MongoTemplate;import org.springframework.data.mongodb.core.query.Query;import org.springframework.data.mongodb.core.query.Update;public class BaseDaoImpl<T> implements IBaseDao<T> {@Autowired protected MongoTemplate mongoTemplate;protected Class<T> clazz;@SuppressWarnings("unchecked")public BaseDaoImpl() { ParameterizedType pt = (ParameterizedType) this.getClass() .getGenericSuperclass(); this.clazz = (Class<T>) pt.getActualTypeArguments()[0];}public void save(T t) {this.mongoTemplate.save(t);}public T findOneById(Object id) {return this.mongoTemplate.findById(id, clazz);}public List<T> findAll() {return this.mongoTemplate.findAll(clazz);}public void deleteByModel(T t) {this.mongoTemplate.remove(t);}public void deleteByQuery(Query query) {this.mongoTemplate.remove(query, clazz);}public void update(Query query, Update update) {this.mongoTemplate.upsert(query, update, clazz);}}
- Mongdb中存储数据关系--------1对多关系
- 多对多关系中,
- 数据存储知识(1)--关系型数据库
- 数据1对多关系的一种思路
- 数据的多对一关系
- 关于hibernate中多对多关系
- Hibernate中多对多关系转换
- hibernate中多对多关系映射
- sqlalchemy中多对多的关系
- hibernate中多对一关系映射
- Android中使用嵌入式关系型SQLite数据库存储数据
- redis中以层级关系、目录形式存储数据
- 多对多关系
- 多对多关系
- SSH框架双向多对多关系中如何向中间表插入数据
- hibernate关联关系之多对多关系
- Hibernate关系映射之多对多关系
- Solr5 DataImport 处理1对多关系
- mac下 硬破解zend studio 12.5.1
- guodingguodingguoding
- [LeedCode OJ]#191 Number of 1 Bits
- Android倒计时的实现代码
- python slice的几个小点总结
- Mongdb中存储数据关系--------1对多关系
- 堆排序1.0
- 离屏Canvas——制作水印图片
- IBM developer Bash系列
- mysql在linux及windows上安装及远程连接
- 家装应该怎么刷涂料
- 又见GCD(http://acm.hdu.edu.cn/showproblem.php?pid=2504)
- 定位高cpu使用率
- POJ1700 Crossing River