问题
I got this structure in my mongodb (2 collections: restaurant
and cocktail
)
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"}
Multiple restaurant
s and multiple cocktail
s, N:N relationship.
My goal is to find which different cocktail
s I can drink within a specified area.
I've already written a query that finds all restaurants near my position like this:
mongoTemplate.find(new Query(Criteria.where("address.location").withinSphere(new Circle(latitude, longitude, radius/6371))
), Restaurant.class);
So that I obtain a list of restaurant
s.
Next steps are:
How to obtain distinct
cocktail
'sid
(no repetitions allowed)How to look into
cocktail
collection in order to obtain allcocktail
names
TY in advance!
回答1:
This might not answer your question completely but can help
how to obtain distinct cocktails id (no repetitions allowed)
Your cocktail
is in array so direct group
or distinct
might not work you can use $unwind
.
What $unwind does is allow you to peel off a document for each element and returns that resulting document
eg: for this object
{id=1001, name="Res1", coor=[12.392, 19.123], cocktail=[13, 0, 92]}
and this query
db.temp.aggregate( [ { $unwind: "$cocktail" } ] )
will result in
{ "_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 }
Now once you have all individual record you can group by cocktail
db.temp.aggregate( [ { $unwind: "$cocktail" },
{
"$group": {
_id: {
"_id": "$_id",
items: {$addToSet: '$cocktail'}}
}
}
}
] );
This should answer your 1st query
For getting cocktail names you need to use lookup, group and project something like this
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()
Note: This is just one approach, might not be the best way and also untested.
回答2:
You can search data from two or more collection using join in MongoDB. Depending on your scenario,the following links might help.
https://www.mongodb.com/blog/post/joins-and-other-aggregation-enhancements-coming-in-mongodb-3-2-part-1-of-3-introduction
回答3:
what about using aggregation.
first perform match stage where you get all restaurant then perform unwind operation on cocktail after this you can perform group by on cocktail field. At this stage you have all unique cocktail id then perform lookup stage .
Order of stage
- match
- project if you want its optional
- unwind
- group
- lookup
- project //because you want only name of cocktail instead of complete collection.
The code is in kotlin just convert it to java if you are using intellij as ide then it will convert it into java for you.
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)
来源:https://stackoverflow.com/questions/56273095/mongodb-how-to-search-in-multiple-collections