mongodb - 使用可搜索的嵌套数组设计 mongodb 模式。
问题描述
我是来自关系数据库的 Mongodb 新手,我还想指出我正在使用 SpringBoot 和 JPA。如果我要建立一个汽车分类网站,其中有成千上万的用户和成千上万的列表,我将如何设置架构?我读过一些文章说规范化 nosql 数据是不好的做法。
无论如何,可以说我们有以下结构。
User
id
name
email
Cars
id
make
model
year
我需要能够与用户一起列出许多汽车,我在示例中看到的是它在用户中创建了一个嵌套的汽车数组。这对于我想为用户提供所有汽车的用户帐户非常有用
我有点困惑的地方是汽车。这些汽车需要能够非常快速地被搜索到,并且不需要立即提供用户信息。在 sql 数据库中,我通常会搜索汽车(年份、品牌、型号),然后在需要时获取用户。
在 mongodb 中,您是否创建了一个包含嵌套汽车数组的用户文档?还是出于性能原因,您是否以某种方式创建了两个自动维护并针对汽车文档进行搜索的文档?
示例代码
@Document(collection = "person")
public class Person {
@Id
private String id;
private String firstName;
private String lastName;
// @DBRef(lazy = true)
private List<Listing> listings;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
@Document(collection = "listing")
public class Listing {
@Id
public String id;
public String year;
public String make;
public String model;
public String trim;
public Listing(String year, String make, String model, String trim) {
this.year = year;
this.make = make;
this.model = model;
this.trim = trim;
}
}
@Override
public void run(String... args) throws Exception {
repository.deleteAll();
List<Listing> listings = new ArrayList<>();
Listing listing = new Listing("2008", "Ford", "Focus", "SE");
//listingRepository.save(listing);
listings.add(listing);
Person person = new Person("Alice", "Smith");
person.setListings(listings);
// save a couple of customers
repository.save(person);
person = new Person("Bob", "Smith");
listings = new ArrayList<>();
listings.add(new Listing("2018", "Chrysler", "300", "S"));
person.setListings(listings);
repository.save(person);
// fetch all customers
System.out.println("Customers found with findAll():");
System.out.println("-------------------------------");
for (Person _person : repository.findAll()) {
System.out.println(_person);
}
System.out.println();
// fetch an individual customer
System.out.println("Person found with findByFirstName('Alice'):");
System.out.println("--------------------------------");
System.out.println(repository.findByFirstName("Alice"));
System.out.println("Persons found with findByLastName('Smith'):");
System.out.println("--------------------------------");
for (Person _person : repository.findByLastName("Smith")) {
System.out.println(_person);
}
List<Listing> _listings = listingRepository.findAll();
System.out.println("listings " + _listings.size());
_listings.forEach(v -> {
System.out.println(v.toString());
});
}
解决方案
按照您的实体模型,我认为您正在寻找的是类似于关系数据库中的多对多/一对多关系。因此,您可以在 MongoDb 中选择一种方式嵌入或两种方式嵌入。
对于单向嵌入,您可以创建一个 Car 集合,如下所示:
db.carCollection.insertMany([{
_id:1,
make: 'porcha',
model:'qwerty',
year:'2018'
},
{
_id:2,
make: 'ferrara',
model:'uiop',
year:'2018'
}])
然后,您可以继续创建用户集合,如下所示:
db.userCollection.insert({
_id:1,
user:'Tom',
email:'tom@tom.com',
car_ids:[1,2]
})
car_ids 是一个数组,它将保存属于用户的汽车的 ID。
您可以获取属于用户的汽车(使用 findOne 获取用户。搜索参数应该是唯一的 id。我认为电子邮件在这里是唯一的。理想情况下,它应该是用户的 id):
var user=db.userCollection.findOne({email:'tom@tom.com'})
db.carCollection.find({_id:{$in:user.car_ids}})
这将为每个用户获取所有汽车
对于取车,您只需执行以下操作:
db.carCollection.find({})
对于双向嵌入,您可以在汽车集合中拥有类似的数组(如在用户集合中),以便可以将每辆车识别给其用户。
推荐阅读
- python - 在 Excel 工作表中搜索字符串并将数据添加到新列
- javascript - 在网站的不同页面中显示不同的地图
- java - 无法运行 CommandLineRunner (Spring Boot)
- typescript - 如何在没有变量的情况下缩小函数参数的类型
- sql - 如何在不使用临时表的情况下检索当前行和先前行的值之间的值差异?
- sql - 随机连接表并返回列
- python - 将 Python 库添加到 Docker 上的 Airflow-Puckel
- javascript - 覆盖 CompilerHost
- google-cloud-platform - 在 Google Cloud Platform 中启用基于角色的支持时遇到一些问题
- java - 三元运算符检查 null 并同时使用 .equals 设置布尔值