MongoDB使用记录
最近爬虫项目在做主题分类的时候需要将爬去规则存到MongoDB中。后台需要集成MongoDB。这里记录一下使用MongoDB的过程。
Spring Data MongoDB - Reference Documentation地址:
http://docs.spring.io/spring-data/data-mongodb/docs/current/reference/html/
1.项目集成MongoDB
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.3.2.RELEASE</version> </dependency>
2.编写MongoDB基础操作类
import java.lang.reflect.ParameterizedType; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import com.mongodb.WriteResult; /** * mongodb 基础操作类 * * @author yangkun * */ public abstract class MongoBaseDao<T> { @Autowired @Qualifier("mongoTemplate") public MongoTemplate mongoTemplate; private Class<T> entityClass; /** * 初始化DAO时使用反射拿到泛型超类的类型参数 */ @SuppressWarnings("unchecked") public MongoBaseDao() { this.entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } /** * 通过条件查询,查询分页结果 * * @param pageNo * @param pageSize * @param query * @return */ public Pagination<T> getPage(int pageNo, int pageSize, Query query) { long totalCount = this.mongoTemplate.count(query, this.entityClass); Pagination<T> page = new Pagination<T>(pageNo, pageSize, totalCount); query.skip(page.getFirstResult());// skip相当于从那条记录开始 query.limit(pageSize);// 从skip开始,取多少条记录 List<T> datas = this.find(query); page.setDatas(datas); return page; } /** * 通过条件查询实体(集合) * * @param query */ public List<T> find(Query query) { return mongoTemplate.find(query, this.entityClass); } /** * 通过一定的条件查询一个实体 * * @param query * @return */ public T findOne(Query query) { return mongoTemplate.findOne(query, this.entityClass); } /** * 查询出所有数据 * * @return */ public List<T> findAll() { return this.mongoTemplate.findAll(this.entityClass); } /** * 查询并且修改记录 * * @param query * @param update * @return */ public T findAndModify(Query query, Update update) { return this.mongoTemplate.findAndModify(query, update, this.entityClass); } /** * 按条件查询,并且删除记录 * * @param query * @return */ public T findAndRemove(Query query) { return this.mongoTemplate.findAndRemove(query, this.entityClass); } /** * 通过条件查询更新数据 * * @param query * @param update * @return */ public void updateFirst(Query query, Update update) { mongoTemplate.updateFirst(query, update, this.entityClass); } /** * 更新多个 * @param query * @param update */ public int updateMulti(Query query, Update update) { WriteResult result = mongoTemplate.updateMulti(query, update, this.entityClass); return result.getN(); } /** * 保存一个对象到mongodb * * @param bean * @return */ public T save(T bean) { mongoTemplate.save(bean); return bean; } /** * 通过ID获取记录 * * @param id * @return */ public T findById(String id) { return mongoTemplate.findById(id, this.entityClass); } /** * 通过ID获取记录,并且指定了集合名(表的意思) * * @param id * @param collectionName * 集合名 * @return */ public T findById(String id, String collectionName) { return mongoTemplate.findById(id, this.entityClass, collectionName); } /** * remove * @param id */ public void remove(Query query) { mongoTemplate.remove(query, entityClass); } /** * 保存全部 * @param list * @return */ public List<T> save(List<T> list) { mongoTemplate.insertAll(list); return list; } }
3.编写AppCategoryDao
import java.util.List; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Repository; import com.cyou.nad.goldlocker.dao.base.MongoBaseDao; import com.cyou.nad.goldlocker.domain.mongo.AppCategory; /** * AppCategoryMongoDao * * @author yangkun * */ @Repository public class AppCategoryMongoDao extends MongoBaseDao<AppCategory> { @Override public AppCategory findById(String unique) { Query q = new Query(Criteria.where("_id").is(unique)); System.out.print(super.findOne(q).getCategory()); return super.findOne(q); } @Override public List<AppCategory> findAll() { Query q = new Query(); return super.find(q); } @Override public AppCategory save(AppCategory app) { mongoTemplate.save(app); return app; } public void remove(String unique) { // TODO Auto-generated method stub Query q = new Query(Criteria.where("_id").is(unique)); Update update = new Update(); update.set("flag_off", 1); mongoTemplate.upsert(q, update, AppCategory.class); } public void remAndinser(AppCategory app) { // TODO Auto-generated method stub String _id = app.get_id(); Query q = new Query(Criteria.where("_id").is(_id)); Update update = new Update(); update.set("category", app.getCategory()); update.set("flag_off", app.getFlag_off()); update.set("ctype", app.getCtype()); update.set("aliases", app.getAliases()); update.set("words", app.getWords()); update.set("related", app.getRelated()); mongoTemplate.updateMulti(q, update, AppCategory.class); } }
4.编程中遇到的问题
1.使用update进行更新,更新的代码为:
String _id = app.get_id(); Query q = new Query(Criteria.where("_id").is(_id)); Update update = new Update();
//这里将要更新的内容通过update对象的set方法设置进去,只需要按照字段即可,无需考虑字段类型。
update.set("category", app.getCategory());
update.set("flag_off", app.getFlag_off());
update.set("ctype", app.getCtype());
update.set("aliases", app.getAliases());
update.set("words", app.getWords());
update.set("related", app.getRelated());
mongoTemplate.updateMulti(q, update, AppCategory.class);
方法解释:
updateMulti:代表更新有相同条件的所有数据。
updateFirst:代表只更新有相同条件的第一条数据。
参数解释:
第一个参数:类似于SQL语句中的where条件。匹配你想更新的数据
第二个参数:需要更新的内容。
第三个参数:要更新的类的Class对象
2.AppCategory获取id问题
import java.util.List; import org.springframework.data.mongodb.core.mapping.Document; import com.cyou.nad.goldlocker.constant.MongoCollections; /** * AppCategory * * @author yangkun * */ @Document(collection=MongoCollections.AppCategory) public class AppCategory { private String _id; private int ctype; private String flag_off; private String category; private List<String> aliases; private List<String> words; private Related related; public int getCtype() { return ctype; } public void setCtype(int ctype) { this.ctype = ctype; } public String get_id() { return _id; } public void set_id(String _id) { this._id = _id; } public String getId() { return _id; } public void setId(String id) { this._id = id; } public String getFlag_off() { return flag_off; } public void setFlag_off(String flag_off) { this.flag_off = flag_off; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public List<String> getAliases() { return aliases; } public void setAliases(List<String> aliases) { this.aliases = aliases; } public List<String> getWords() { return words; } public void setWords(List<String> words) { this.words = words; } public Related getRelated() { return related; } public void setRelated(Related related) { this.related = related; } }
问题:这里需要根据Mongo自动生成的_id字段去更新内容,前台是通过JSON传递到Controller的,使用fastJson去解析JSON,但是解析出来的app类的_id总是不会被设置上值。导致无法通过_id被更新。
AppCategory app = JSONObject.parseObject(jsonStr, AppCategory.class);
于是想到是不是因为AppCategory的_id属性名称的命名问题,导致反射的时候调用不到set方法导致的。于是创建一个新的字段命名为:id,提供get和set方法,在id的set方法中调用_id的set方法。然后问题解决。但是后续因为项目进度原因没有继续研究到底是不是fastJSON的问题,还是别的。不过在之后的pojo的命名方式提供了借鉴。