MongoTemplate project Object as List of one Object - mongodb

I'm using spring MongoTemplate and I have objects like below
The main objects,
{
id: "001",
name: "one",
age: 12,
hobby: "a"
}
{
id: "001",
name: "one",
age: 12,
hobby: "b"
}
The projection result,
{
id: "001",
name: "one",
hobbyList: ["a", "b"]
}
This is the aggregate I'm using so far. It's not working and I don't have an idea how to combine those two objects. How can I fix this?
mongoTemplate.aggregate(newAggregation(project("user.id","user.name")
.and("hobby").as("hobbyList")), "User", User.class).getMappedResults();

You can use group and project operation to achieve this,
First we'll group id, name, age under _id attribute and push all common hobbies to hobbyList attribute.
Then use project is to pull out all the grouped result and exclude _id
newAggregation(
Aggregation.group("id", "name", "age").push("hobby").as("hobbyList"),
Aggregation.project("_id.id", "_id.name", "_id.age", "hobbyList").andExclude("_id")
)

Related

How to add multiple filters to the same document key in mongoose?

I currently have an array of objects in a document that looks something like this:
users: [
{name: "Bob", age: 23},
{name: "Tom", age: 23),
{name: "Sam", age: 26),
]
I am trying to find the document that has the name Bob and the age 23. while filtering out any documents that do not match this criteria, or do not yet exist. I was able to find the matching object with:
User.find({users: { $elemMatch: { name: "Bob", age: 23}}})
and I was able to filter out the documents that do not exist with:
User.find({users: {$ne: []}})
but when I try to add the two together, like so, the program stops working:
User.find({users: {$ne: [], $elemMatch: { name: "Bob", age: 23}}})
I want to know how to can add two filters for the same key inside the document.

How to search a Mongo collection for a document that contains an array that contains an element that meets a particular criteria?

I'm new at Mongo and there might be a better way to do what I want. I'm dealing with a particular data structure that my application must process.
Suppose that I have a collection that contains two documents that contain information about universities and their student clubs to include the name of each club and the name of each student in each club along with their age:
{
_id: 1, // object ID
name: "Oxford University",
clubs: [{
name: "Soccer",
members: [{
name: "Alice",
age: 22
},
{
name: "Bob",
age: 23
}
]
}, {
name: "Gymnastics",
members: [{
name: "Charlie",
age: 20
},
{
name: "Dorothy",
age: 19
}
]
}]
}
{
_id: 2, // object ID
name: "Cambridge University",
clubs: [{
name: "Chess",
members: [{
name: "Ellen",
age: 30
},
{
name: "Frank",
age: 35
}
]
}, {
name: "Go",
members: [{
name: "Gilbert",
age: 25
},
{
name: "Hikari",
age: 40
}
]
}]
}
Suppose that I want to write a query on this collection that will find universities that have a club that has at least one member aged 40 or older.
How do I do that?
I sketched this example based off of the idea of taking some JSON documents and inserting them into a new collection. Maybe it would be a better idea to break this apart into multiple collections. I just had the idea to research if Mongo might be a good product to use in this situation given that a big part of my job here is to create something that can receive some JSON data, process it, and make it queryable.
MongoDB queries have a convenient feature to query documents that have a specific value or condition in embedded objects and arrays. In the query you can specify the "path" to the object or array using "dot notation" without having to specify the exact array index, etc.
Using your example, you can find the documents where a member of a club is aged 40 or older like this.
db.collection.find({
"clubs.members.age": {
"$gte": 40
}
})
This returns the second document in your example collection.
Try it on mongoplayground.net.

Find matching field in an array of objects in an object with go mongo-driver

My mongo database has a structure like this. Given a parent _id, for example, 123, how can I make a query to check if item abc exists in its parent 123?
[
- _id: 123
name: "item 1"
items: [
{
_id: abc,
age: 12,
},
{
_id: efg,
age: 12,
}
]
,
- id: 456
name: "item 2"
items: [
...
]
]
I currently have this and I've tried $elemMatch but it doesn't seem to work.
db.Collection("album").FindOne(context.Background(), bson.M{"_id": parentID})
It is not clear if items has separate documents, or if it is a nested array in the document. Either case:
If items is a nested array in the document, then:
bson.M{"_id":parentID,"items._id":"abc"}
will find documents whose _id is parentID and that contains _id:"abc" in one of the elements of items.

List all values existing of a property?

Assume I have a Student collection:
{
name: "ABC",
age: 10,
address {
city: "CITY1",
state: "STATE",
}
}
{
name: "DEF",
age: 11,
address {
city: "CITY2",
state: "STATE",
}
}
{
name: "ABC",
age: 12,
address {
city: "CITY1",
state: "STATE",
}
}
Can I get the list of all unique City values from the list? For example, with the above 3 documents, I would like to get the list {"CITY1", "CITY2"}
I was just getting started with MongoDB from Relational Database, so this is a little confused for me, since I needed another Address table for it and I can just use SELECT DISTINCT to get what I want.
MongoDB has a similar db.collection.distinct() command.
To access elements in the address subdocument you need to use dot notation, so the complete query would be:
db.Student.distinct("address.city")
Some helpful documentation links to help you make the translation from SQL queries:
SQL to MongoDB Mapping Chart
SQL to Aggregation Mapping Chart
Just for notes, there is already distinct as mentioned, but for a more conventional response, use aggregate:
db.Student.aggregate([
{"$unwind": "$address" }},
{"$group": { "_id": "$address.city" }},
{"$project": { "_id": 0, "city" : "$_id" }}
])
Long winded compared to distinct, but it depends on what your eyes want.

MongoDB - $addToSet on a list of Embedded Document

I have a list of (mongodb) Embedded Documents within one Document and I am interested in adding a new embedded document to the list of the existing ones.
As far as I have researched, I can use $addToSet, what I can't figure out is how does MongoDB decide if the new document already exists in the list of embedded documents or if it's a new one, i.e. how does MongoDB decide if 2 embedded documents are equal?
p.s. the embedded documents I have are not just values, they are quite complex structures, so I was wondering if there is any place I can define what the equality between 2 of them means...
$addToSet uses the usual mongodb equality rules: it will do a deep value-by-value comparison, so the following two documents are identical:
{ name: "John", hobbies: ["coding", "drinking", "chess"] }
{ hobbies: ["coding", "drinking", "chess"], name: "John" }
(order within documents is not guaranteed, so they are identical)
while those aren't (pairwise):
// compare to:
{ name: "John", hobbies: ["chess", "coding", "drinking"] }
// in arrays, the order matters:
{ name: "John", hobbies: ["coding", "drinking", "chess"] }
// field names and values are case sensitive
{ Name: "John", hobbies: ["chess", "coding", "drinking"] }
{ name: "john", hobbies: ["chess", "coding", "drinking"] }
// additional field:
{ name: "John", lastName: "Doe", hobbies: ["chess", "coding", "drinking"] }
// missing field:
{ name: "John" }
Please note that there is no special field here. You can add an _id field, but it has no special semantics and will be treated just like any other field.