【问题标题】:MongoDb: how to search in multiple collections?MongoDb:如何在多个集合中搜索?
【发布时间】:2019-05-23 10:19:51
【问题描述】:

我的 mongodb 中有这个结构(2 个集合:restaurantcocktail

restaurant {id=1001, name="Res1", coor=[12.392, 19.123], cocktail=[13, 0, 92]}

cocktail {id=13, name="Capiroska"}, {id=167, name="Capirinha"}, {id=92, name="Negroni"}, {id=0, name="Martini"}

多个restaurants 和多个cocktails,N:N 关系。

我的目标是找出我可以在指定区域内喝到哪些不同的cocktails。

我已经写了一个查询来查找我位置附近的所有餐馆,如下所示:

mongoTemplate.find(new Query(Criteria.where("address.location").withinSphere(new Circle(latitude, longitude, radius/6371))
            ), Restaurant.class);

这样我就获得了restaurants 的列表。

接下来的步骤是:

  1. 如何获得不同的cocktailid(不允许重复)

  2. 如何查看cocktail 集合以获取所有cocktail 名称

提前TY!

【问题讨论】:

标签: spring mongodb mongodb-query spring-mongodb


【解决方案1】:

这可能无法完全回答您的问题,但可以提供帮助

如何获得不同的鸡尾酒 ID(不允许重复)

您的cocktail 在数组中,所以直接groupdistinct 可能不起作用,您可以使用$unwind

$unwind 的作用是允许你为每个元素剥离一个文档 并返回结果文档

例如:对于这个对象

{id=1001, name="Res1", coor=[12.392, 19.123], cocktail=[13, 0, 92]}

还有这个查询

db.temp.aggregate( [ { $unwind: "$cocktail" } ] )

将导致

{ "_id" : 1001, "name" : "Res1", coor=[12.392, 19.123],, "cocktail" : 13 }
{ "_id" : 1001, "name" : "Res1", coor=[12.392, 19.123],, "cocktail" : 0 }
{ "_id" : 1001, "name" : "Res1", coor=[12.392, 19.123],, "cocktail" : 92 }

现在,一旦您拥有所有个人记录,您就可以按鸡尾酒分组

db.temp.aggregate( [ { $unwind: "$cocktail" },
    {
     "$group": {
             _id: {
                     "_id": "$_id",
                     items: {$addToSet: '$cocktail'}}
            }
        }
    }
 ] );

这应该会回答您的第一个问题

要获取鸡尾酒名称,您需要使用类似这样的查找、分组和项目

db.temp.aggregate([
    {
        "$unwind": "$cocktail"       
    },
    {
        "$lookup": {
            "from": "cocktail ",
            "localField": "restaurant.cocktail._id",
            "foreignField": "_id",
            "as": "cocktails"
        }
    },  
    { "$unwind": "$cocktails" },
    {
        "$group": {
            "_id": "$_id",
            "cocktail": { "$cocktail": "$cocktail" },
        }
    },
    {
        "$project": {
            "name": 1,  
            "coor" : 1,
            "cocktail.name" : 1,
        }
    }
]).pretty()

注意:这只是一种方法,可能不是最好的方法,也未经测试。

【讨论】:

    【解决方案2】:

    您可以在 MongoDB 中使用 join 从两个或多个集合中搜索数据。 根据您的情况,以下链接可能会有所帮助。

    https://www.mongodb.com/blog/post/joins-and-other-aggregation-enhancements-coming-in-mongodb-3-2-part-1-of-3-introduction

    【讨论】:

      【解决方案3】:

      如何使用聚合。

      首先进行比赛阶段,获得所有餐厅,然后对鸡尾酒进行放松操作,之后您可以在鸡尾酒场上进行分组。在这个阶段,您拥有所有唯一的鸡尾酒 ID,然后执行查找阶段。

      舞台顺序

      1. 匹配
      2. 如果你想要它的可选项目
      3. 放松
      4. 查找
      5. project //因为你只想要鸡尾酒的名字而不是完整的 收藏。

      代码在 kotlin 中,如果您使用 intellij 作为 ide,只需将其转换为 java,然后它将为您将其转换为 java。

      var match = Aggregation.match(Criteria.where("address.location").withinSphere(Circle(latitude, longitude, radius / 6371)))
              var project = Aggregation.project("cocktail")
              var unwind = Aggregation.unwind("cocktail")
              var group = Aggregation.group("cocktail")
              var lookup = Aggregation.lookup("your cocktail collection name","_id.cocktail","id","cocktailCollection")
              var project1 = Aggregation.project("cocktailCollection.name").andExclude("_id")
      
          var aggregation = Aggregation.newAggregation(match,project,unwind,group,lookup,project1)
      
          println(aggregation) // if you want to see the query
      
          var result = mongoTemplate.aggregate(aggregation,String::class.java)
      

      【讨论】:

      • TY 的答案,但不幸的是,我是 MongoDB 的新手,我不知道如何将您刚刚写的内容翻译成代码。
      • 我就这样解决了List<ObjectId> restaurantList = mongoTemplate.findDistinct( new Query( Criteria.where("address.location").withinSphere(new Circle(latitude, longitude, radius / 6371)) ), "cocktailList", Restaurant.class, ObjectId.class ); return cocktailRepository.findBy_idIn(new HashSet<>(restaurantList));
      猜你喜欢
      • 2013-12-02
      • 1970-01-01
      • 2021-04-17
      • 2014-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      相关资源
      最近更新 更多