Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

53.3. @Document

复杂的 @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 + "]";
	}

}
		
		

53.3.1. 指定表名

默认使用 class 作为表名

			
@Document
public class Multilevel {
	...
	...
}			
			
			

指定特别表名

			
@Document(collection = "author")			
			
			

53.3.2. @Id

			
	@Id
	private String id;		
			
			

53.3.3. @Version

			
	@Version 
	private Long version;			
			
			

53.3.4. @Field 定义字段名

			
@Field("url")
private String link;			
			
			

53.3.5. @Indexed

https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/index/Indexed.html

索引

53.3.5.1. 普通索引

				
@Indexed		
				
				

53.3.5.2. 唯一索引

				
@Indexed(unique=true)	
				
				

53.3.5.3. 索引排序方式

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

53.3.5.4. 稀疏索引

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

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

53.3.5.5. 索引过期时间设置

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

53.3.6. @CompoundIndex 复合索引

53.3.6.1. 普通复合索引

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

53.3.6.2. 唯一复合索引

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

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

不允许同名

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

53.3.7. @TextIndexed

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

    @TextIndexed String foo;

    @Language String lang;

    Nested nested;
}

class Nested {

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

53.3.8. @GeoSpatialIndex 地理位置索引

点数据索引

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

2D 数据索引

				
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)				
				
			

53.3.9. @Transient 丢弃数据,不存到 mongodb

			
public class User {
     
    @Transient
    private Integer age;

    // standard getter and setter
 
}	
			
			

53.3.10. @DBRef 做外外键引用

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

}
				
				
				

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

}

				
				

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

}
				
				

53.3.10.4. 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;
	}

}
				
				
				

53.3.10.5. 运行结果

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

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

53.3.12. @NumberFormat

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

53.3.13. 在 @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;			
			
			

53.3.14. 在 @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;
			
			

53.3.15. GeoJson 数据类型

			
	@GeoSpatialIndexed
	private GeoJsonPoint location; // GPS 地址位置
			
			
			
location = new GeoJsonPoint(Double.valueOf(longitude), Double.valueOf(latitude));