spring - 如何用父文档展平动态字段 - 没有 Mongodb 聚合的 Spring data Mongo DB
问题描述
文档看起来像:
@Document(collection="Contact")
public class Contact {
@Id
private String id;
private Map<String, String> properties;
}
存储库是这样的:
@Repository
public interface ContactRepository extends MongoRepository<Contact, String> {
}
这会将数据保存在数据库中,如下所示:
_id: "5f16699eb57ab928fdf0e893",
properties:
{
customField: "customValue"
}
但我想要这样的结果:
_id: "5f16699eb57ab928fdf0e893",
customField: "customValue"
解决方案
我已经进行了研究,您可以通过实现自己的自定义转换器来做到这一点(如此处所述:https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.自定义转换器)
解决方案是:
- 创建您的特定转换器,一个给读者,另一个给作者
import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
import java.util.HashMap;
import java.util.Map;
public class ContactReadConverter implements Converter<Document, Contact> {
@Override
public Contact convert(Document source) {
Contact c = new Contact();
c.setId((Long) source.get("_id"));
Map<String, String> props = new HashMap<>();
source.keySet().stream()
.filter(key -> !key.equals("_id"))
.forEach(key -> props.put(key, (String) source.get(key)));
c.setProperties(props);
return c;
}
}
import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
public class ContactWriteConverter implements Converter<Contact, Document> {
@Override
public Document convert(Contact source) {
Document dbo = new Document();
dbo.put("_id", source.getId());
source.getProperties()
.forEach(dbo::put);
return dbo;
}
}
- 然后,您需要将这些转换器添加到 MongoDB 中。这是我的做法:
@SpringBootApplication
public class MainClass {
...
@Bean
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<>();
converterList.add(new ContactReadConverter());
converterList.add(new ContactWriteConverter());
return new MongoCustomConversions(converterList);
}
}
还有我的Contact
班级,以防万一:
import org.springframework.data.mongodb.core.mapping.Document;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Map;
@Document
public class Contact {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private Map<String, String> properties;
public Contact() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
@Override
public String toString() {
return "Contact{" +
"id=" + id +
", properties=" + properties +
'}';
}
}
我的结果是:
{“_id”:NumberLong(0),“toto”:“titi”,“tata”:“tonton”}
需要考虑的事项:
- 根据您的需要进行定制。因为使用提供的解决方案,您将解释您可能拥有的所有其他字段并将其存储到您的地图中。哪个不太好...
- 小心,我希望默认转换器对“基本”mongo 配置没有影响。
推荐阅读
- sas - 计算过去 x 年的平均值
- elixir - Elixir / Phoenix - 发送后从控制器操作中删除文件
- cassandra - 使用Java驱动程序获取数据时如何防止Cassandra Set重新排序
- r - 使用自定义 .csl 文件进行参考书目时,Rstudio 中的编织 .Rmd 文件挂起
- scala - 在 Scala Spark 中,我如何分组并将组的每个值除以该组中的行数
- python - 需要帮助将图像添加到函数内的 Tkinter 窗口中吗?
- .net - Balloon WinApi 弹出窗口中的非 ascii 字符
- mongodb - Mongorestore 不起作用(无效的 BSON 大小错误)
- rust - mio 什么时候做 epoll 实例?
- javascript - 发送表单时更改按钮/图标