使用可搜索的嵌套数组设计mongodb模式。

时间:2018-10-10 04:27:29

标签: mongodb spring-boot

我是来自关系数据库的Mongodb的新手,我也想指出我在JPA中使用SpringBoot。如果要建立一个汽车分类站点,在那里我将拥有成千上万的用户和成千上万的列表,那么我将如何设置架构?我读过一些文章说规范nosql数据是不好的做法。

无论如何,我们有以下结构。

User
  id
  name
  email

Cars
  id
  make
  model
  year

我需要能够与User列出许多汽车,而我在示例中看到的是,它在User中创建了嵌套的汽车阵列。对于我想为用户提供所有汽车的用户帐户,这将非常有用

我有点困惑的是汽车。这些汽车需要能够非常快速地被搜索,并且不需要立即获取用户信息。在sql db中,我通常会针对汽车(年份,品牌,型号)进行搜索,并在以后需要时吸引用户。

在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());
    });
}

1 个答案:

答案 0 :(得分:1)

按照您的实体模型,我认为您正在寻找的内容类似于关系数据库中的多对多/一对多关系。因此,您可以在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({})

对于双向嵌入,您可以在cars集合内具有类似的数组(如在用户集合中),以便可以向其用户标识每辆车。