先列提纲,后续有时间再完善
1.配置
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
如果使用默认的配置一行搞定, 如果用户名和密码中有:和@符号,需要进行urlencode,@用%40替换,假如密码是123@admin,那么就要写成123%40admin,源码中在设置用户名和密码的时候根据:和@符号进行劈分,然后URLDecoder.decode(input, "UTF-8")
spring.data.mongodb.uri=mongodb://admin:[email protected]:27017/admin
多数据源
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class, MongoDataAutoConfiguration.class})
mongod.user.uri=mongodb://admin:[email protected]:27017/admin
mongod.article.uri=mongodb://admin:[email protected]:27017/article
@Configuration
@ConfigurationProperties(prefix="mongod.user")
@EnableMongoRepositories(basePackages={"com.**.repository.user"},mongoTemplateRef = "mongoUserTemplate")
public class MongoUserConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(MongoUserConfig.class);
private String uri;
public MongoDbFactory simpleFactory() throws Exception {
return new SimpleMongoDbFactory(new MongoClientURI(uri));
}
@Bean(name="mongoUserTemplate")
public MongoTemplate mongoUserTemplate() throws Exception {
LOGGER.info("init mongodb template uri={}", uri);
return new MongoTemplate(simpleFactory());
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
@Data
@Configuration
@ConfigurationProperties(prefix="mongod.content")
@EnableMongoRepositories(basePackages={"com.**.repository.content"},mongoTemplateRef = "mongoContentTemplate")
public class MongoUserConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(MongoUserConfig.class);
private String uri;
public MongoDbFactory simpleFactory() throws Exception {
SimpleMongoDbFactory factory = new SimpleMongoDbFactory(new MongoClientURI(uri));
factory.setWriteConcern(WriteConcern.MAJORITY.withJournal(true));
return factory;
}
@Bean(name="mongoContentTemplate")
public MongoTemplate mongoContentTemplate() throws Exception {
LOGGER.info("init mongodb template uri={}", uri);
return new MongoTemplate(simpleFactory());
}
}
2.注解
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Version;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Date;
@Data
public abstract class DocBase {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected String id;
@Version
protected Long version;
@CreatedDate
protected Date createdDate;
@LastModifiedDate
protected Date lastModifiedDate;
}
@Data
@Document(collection = "article")
@CompoundIndexes({
@CompoundIndex(name = "article_revision_idx", def = "{ 'id' : 1, 'revision': -1}", unique = true)
})
public class Article extends DocBase{
@Indexed
private String userId;
private int revision;
private String content;
private String articleId;
@DBRef
@NotNull
private List<Attachment> attachments = Collections.emptyList();
@Transient
private boolean hasModifiled;
}
@Indexed 单一索引
@CompoundIndexes 符合索引
@DBRef 外部集合文档引用,官方说如果引用不多的话建议还是自己存一个另外一个集合文档的ID,多一次查询
@Transient 字段不入库,做为处理的中间字段
3.MongoRepository查询和mongoTemplate
repository可以指定返回部分字段
@Query(query="?1",fields="?2") List<Result> findPart(Map<Object,Object> query,Map<String,Integer> fileds)
new Query(Criteria)
new BasicQuery(DBObject,DBObject),第二个参数可以指定返回的字段
QueryBuilder没有用过
List<String> articleIds = Arrays.asList<>("1","2");
List<String> fields = Arrays.asList<>("aricleId","content");
Criteria c = Criteria.where("articleType").is("news").and("revision").is(1).and("articleId").in(articleIds);
DBObject fieldsDB = new BasicDBObject();
fields.forEach(s->fieldsDB.put(s,true));
Query query = new BasicQuery(c.getCriteriaObject(),fieldsDB);
return mongoTemplate.find(query, Question.class, collectionName);
分页排序查询,注意页码是从1开始,即第1页的pageSize = 1
Pageable pageable = new PageRequest(1, 10, new Sort(Sort.Direction.DESC, "lastModifiedDate"));
原子更新操作
mongoTemplate.updateFirst(new Query(where("id").is(counter.getId())), new Update().inc("data." + key, 1), Counter.class);
4.Convert
这里只是记录一下可以改变插入的数据,和读出的数据
public class MongoDBConfig extends AbstractMongoConfiguration {
@Bean
@Override
public CustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
converterList.add(new TreeReadConverter());
converterList.add(new TreeWriteConverter());
return new CustomConversions(converterList);
}
}
@ReadingConverter
public class TreeReadConverter implements Converter<DBObject, Tree<?>> {
private static final Logger LOG = LoggerFactory.getLogger(TreeReadConverter.class);
@Override
public Tree<?> convert(DBObject source) {
//TODO 读出来的时候可以自己对数据进行加工处理
return null;
}
}
@WritingConverter
public class TreeWriteConverter implements Converter<Tree<?>, DBObject> {
private static final Logger LOG = LoggerFactory.getLogger(TreeWriteConverter.class);
@Override
public DBObject convert(Tree<?> source) {
// TODO 在保存数据的时候可以自己对数据对象进行变更
return null;
}
}
5. MongoRepository实现自定义接口
在 repositoryImpl中利用mongoTemplate实现自定义接口的方法,会自动扫描后缀Impl的类
interface IArticleHistory {
Article insertToHistory(Article article);
}
public interface ArticleRepository extends MongoRepository<Question, String>, IArticleHistory {
}
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
class ArticleRepositoryImpl implements IArticleHistory {
private String collectionName = "articleHistory";
@Inject
private MongoTemplate mongoTemplate;
@PostConstruct
void createReleaseCollection() {
DBObject indexKeys = BasicDBObjectBuilder.start("articleId", 1)
.add("reVision", -1)
.get();
DBObject indexOptions = BasicDBObjectBuilder.start("unique", true).get();
BasicDBObjectBuilder.start("keys", indexKeys).add("options", indexOptions).get();
mongoTemplate.getCollection(collectionName).createIndex(indexKeys, indexOptions);
}
@Override
public Article insertToHistory(Article article) {
article.setId(null);
mongoTemplate.insert(article, collectionName);
return article;
}
}
6.备注
mongo会自动去除空字符串或者null的字段
mongodb默认的排序有一个32M内存大小限制,可以通过对排序字段增加索引或者增大32M的限制来解决,但是建议在Java层去做排序