Spring Data with MongoDB (二)

Spring Data with MongoDB

节选自《Netkiller Spring Cloud 手札》

 

复杂的 @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") 

@Id

 @Id
 private String id; 

@Version

 @Version 
 private Long version; 

@Field 定义字段名

@Field("url")
private String link; 

@Indexed

索引

普通索引

@Indexed 

唯一索引

@Indexed(unique=true) 

索引排序方式

@Indexed(name = "first_name_index", direction = IndexDirection.DESCENDING) 

稀疏索引

稀疏索引允许唯一索引存在多个 null 值

 @Indexed(unique = true, sparse = true)
 private String uuid;
 @Indexed(unique = true, sparse = true)
 private String transactionId = null;

索引过期时间设置

@Indexed(name = "expire_after_seconds_index", expireAfterSeconds = 10)
private LocalDateTime updateDate; 

@CompoundIndex 复合索引

普通复合索引

@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
} 

唯一复合索引

唯一复合索引:楼层和房号不能相同,不然就是同一个房间了

@CompoundIndexes({ 
 @CompoundIndex(name = "floor_num", def = "{'floor' : 1, 'num': 1}",unique=true) 
}) 

不允许同名

@CompoundIndexes({ @CompoundIndex(name = "username", def = "{'firstname' : 1, 'lastname': 1}", unique = true) }) 

@TextIndexed

@Document(language = "spanish")
class SomeEntity {

 @TextIndexed String foo;

 @Language String lang;

 Nested nested;
}

class Nested {

 @TextIndexed(weight=5) String bar;
 String roo;
} 

@GeoSpatialIndex 地理位置索引

点数据索引

 @GeoSpatialIndexed
 private GeoJsonPoint location; // GPS 定位信息

2D 数据索引

@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE) 

@Transient 丢弃数据,不存到 mongodb

public class User {
 @Transient
 private Integer age;

 // standard getter and setter
} 

@DBRef 做外外键引用

Article 类

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 + "]";
 }

}

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 + "]";
 }

}

MongoRepository

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> {

}

RestController

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

@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(); 

@NumberFormat

 @NumberFormat(style=Style.CURRENCY)
 private double money;

在 @Document 中使用 Enum 类型

 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; 

在 @Document 中定义数据结构 List/Map

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;

GeoJson 数据类型

 @GeoSpatialIndexed
 private GeoJsonPoint location; // GPS 地址位置
location = new GeoJsonPoint(Double.valueOf(longitude), Double.valueOf(latitude)); 
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

netkiller-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值