知乎专栏 |
复杂的 @Document 数据类型定义
package cn.netkiller.domain; import java.util.Date; import java.util.List; import java.util.Map; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document public class MultilevelDirectSellingTradingRebate { public enum Type { POINT, CASH, GIFT } public enum Rebate { DIRECT, INDIRECT } public enum Status { New, Rejected, Approved } @Id private String id; public String name; public Date beginDate; public Date endDate; public double lowAmount; public double highAmount; public Type type; public Status status = Status.New; public List<Map<String, Map<?, ?>>> product; @Override public String toString() { return "MultilevelDirectSellingTradingRebate [id=" + id + ", name=" + name + ", beginDate=" + beginDate + ", endDate=" + endDate + ", lowAmount=" + lowAmount + ", highAmount=" + highAmount + ", type=" + type + ", status=" + status + ", product=" + product + "]"; } }
默认使用 class 作为表名
@Document public class Multilevel { ... ... }
指定特别表名
@Document(collection = "author")
索引
稀疏索引允许唯一索引存在多个 null 值
@Indexed(unique = true, sparse = true) private String uuid; @Indexed(unique = true, sparse = true) private String transactionId = null;
@Document @CompoundIndexes({ @CompoundIndex(name = "email_age", def = "{'email.id' : 1, 'age': 1}") }) public class User { // }
@Document @CompoundIndexes({ @CompoundIndex(def = "{'firstName':1, 'salary':-1}", name = "compound_index_1"), @CompoundIndex(def = "{'secondName':1, 'profession':1}", name = "compound_index_2") }) public class Person { @Id private String id; private String firstName; private String secondName; private LocalDateTime dateOfBirth; private Address address; private String profession; private int salary; // constructor // getters and setters }
@Document(language = "spanish") class SomeEntity { @TextIndexed String foo; @Language String lang; Nested nested; } class Nested { @TextIndexed(weight=5) String bar; String roo; }
点数据索引
@GeoSpatialIndexed private GeoJsonPoint location; // GPS 定位信息
2D 数据索引
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
public class User { @Transient private Integer age; // standard getter and setter }
package cn.netkiller.api.domain; import java.util.List; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; @Document public class Article { private String title; // 名称 private String description; // 描述 private String tag; // 类型 @DBRef private List<Hypermedia> hypermedia; // 图片,视频 public Article() { // TODO Auto-generated constructor stub } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } public List<Hypermedia> getHypermedia() { return hypermedia; } public void setHypermedia(List<Hypermedia> hypermedia) { this.hypermedia = hypermedia; } @Override public String toString() { return "Article [title=" + title + ", description=" + description + ", tag=" + tag + ", hypermedia=" + hypermedia + "]"; } }
package api.domain; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document public class Hypermedia { @Id private String id; private String hash; private String name; private String size; public Hypermedia() { // TODO Auto-generated constructor stub } public Hypermedia(String hash, String name, String size) { this.hash = hash; this.name = name; this.size = size; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getHash() { return hash; } public void setHash(String hash) { this.hash = hash; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSize() { return size; } public void setSize(String size) { this.size = size; } @Override public String toString() { return "Hypermedia [id=" + id + ", hash=" + hash + ", name=" + name + ", size=" + size + "]"; } }
如果你只查询 Article 表,不会单独查询 Hypermedia,返回结果可以掩藏 Id ,不写 get/set 方法即可。
package cn.netkiller.api.domain; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document public class Hypermedia { @Id private String id; private String hash; private String name; private String size; public Hypermedia() { // TODO Auto-generated constructor stub } public Hypermedia(String hash, String name, String size) { this.hash = hash; this.name = name; this.size = size; } public String getHash() { return hash; } public void setHash(String hash) { this.hash = hash; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSize() { return size; } public void setSize(String size) { this.size = size; } @Override public String toString() { return "Hypermedia [hash=" + hash + ", name=" + name + ", size=" + size + "]"; } }
package cn.netkiller.api.repository; import org.springframework.data.mongodb.repository.MongoRepository; import api.domain.Article; public interface ArticleRepository extends MongoRepository<Article, String> { }
package cn.netkiller.api.repository; import org.springframework.data.mongodb.repository.MongoRepository; import api.domain.Hypermedia; public interface HypermediaRepository extends MongoRepository<Hypermedia, String> { }
package cn.netkiller.api.restful; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import api.domain.Article; import api.domain.Hypermedia; import api.repository.ArticleRepository; import api.repository.HypermediaRepository; @RestController @RequestMapping("/article") public class ArticleRestController { @Autowired private ArticleRepository articleRepository; @Autowired private HypermediaRepository hypermediaRepository; public ArticleRestController() { // TODO Auto-generated constructor stub } @GetMapping("/save") public Article save() { Article article = new Article(); article.setTitle("标题"); article.setDescription("摘要"); article.setTag("标签"); Hypermedia hypermedia = new Hypermedia("AAA", "BBB", "CCC"); hypermediaRepository.save(hypermedia); List<Hypermedia> hypermedias = new ArrayList<Hypermedia>(); hypermedias.add(hypermedia); article.setHypermedia(hypermedias); articleRepository.save(article); System.out.println(article); return article; } }
neo@MacBook-Pro ~ % curl -s -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer ${TOKEN}" -X GET ${URL}/article/save | jq { "title": "标题", "description": "摘要", "tag": "标签", "hypermedia": [ { "hash": "AAA", "name": "BBB", "size": "CCC" } ] }
MongoDB 结果
db.getCollection('article').find({})
/* 1 */ { "_id" : ObjectId("5bab66f8c92782395817cb05"), "title" : "标题", "description" : "摘要", "tag" : "标签", "hypermedia" : [ { "$ref" : "hypermedia", "$id" : ObjectId("5bab66f8c92782395817cb04") } ], "_class" : "cn.netkiller.api.domain.Article" }
db.getCollection('hypermedia').find({})
/* 1 */ { "_id" : ObjectId("5bab66b9c927823951f4f5fe"), "hash" : "AAA", "name" : "BBB", "size" : "CCC", "_class" : "api.domain.Hypermedia" }
@DateTimeFormat( pattern = "yyyy-MM-dd" ) private Date birthday @DateTimeFormat(iso = DateTimeFormat.ISO.NONE) private final Calendar datetime; @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date date; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) private Date createdDate = new Date();
public enum Type { POINT, CASH, GIFT } public enum Rebate { DIRECT, INDIRECT } public enum Status { New, Rejected, Approved }
枚举类型的赋值方法
MultilevelDirectSellingTradingRebate multilevelDirectSellingTradingRebate = new MultilevelDirectSellingTradingRebate(); multilevelDirectSellingTradingRebate.name = "TEST"; multilevelDirectSellingTradingRebate.beginDate = new Date(); multilevelDirectSellingTradingRebate.endDate = new Date(); multilevelDirectSellingTradingRebate.lowAmount = 1.5d; multilevelDirectSellingTradingRebate.highAmount = 100d; multilevelDirectSellingTradingRebate.type = Type.CASH;
public List<Map<String, Map<?, ?>>> product;
下面是数据集结构的赋值例子
Map<Enum<Rebate>, Double> rebate = new HashMap<Enum<Rebate>, Double>(); rebate.put(Rebate.DIRECT, 10.05d); rebate.put(Rebate.INDIRECT, 6.05d); Map<String, Map<?, ?>> prod1 = new HashMap<String, Map<?, ?>>(); prod1.put("USDRMB", rebate); List<Map<String, Map<?, ?>>> products = new ArrayList<Map<String, Map<?, ?>>>(); products.add(prod1); multilevelDirectSellingTradingRebate.product = products;