mongo db pull element out of an array [duplicate] - mongodb

This question already has answers here:
How to remove a field completely from a MongoDB document?
(18 answers)
Closed 4 years ago.
I have a small mongo document which looks like this:
{
"_id": {
"$oid": "5aa441e898cc0b32a819be0c"
},
"details": {
"Artist": "Cyndi Lauper",
"Album": "She's So Unusual",
"ReleaseYear": 1983
},
"SongID": 1,
"SongTitle": "Girls Just Want To Have Fund"
}
I need to pull the Artist element out of the details array but keep the data in the overall document. The resulting document needs to look like this:
{
"_id": {
"$oid": "5aa441e898cc0b32a819be0c"
},
"details": {
"Album": "She's So Unusual",
"ReleaseYear": 1983
},
"SongID": 1,
"SongTitle": "Girls Just Want To Have Fund",
"Artist": "Cyndi Lauper"
}
I'm new to mongo so I'm not to strong in this. The collection is called songs so am thinking I need to do something like this:
db.songs.updateOne({},{$set : {"Artist":$pull{"detail.Artist"}}})
Any help and/or suggestions are greatly appreciated.
Jonathan

You can write something like this in the MongoDB shell:
var doc={doc:{key42:"value"},somekey:"value"};
doc.key42=doc.doc.key42;
delete doc.doc.key42;
After that you can write
doc
and press enter.
The output shold be:
{doc:{},somekey:"value",key42:"value"};
Then you can save the doc:
db.collection.save(doc);

Related

mongodb query object inside an array [duplicate]

This question already has answers here:
Query for a field in an object in array with Mongo?
(2 answers)
Closed 3 years ago.
So I have a collection called Transaction that is structured like the following
{
"_id": "1",
"type": "purchase",
"amount": 11.8,
"relatedObjects": [
{
"eventId": "123131313131322"
}
],
"paymentMethod" : "method1"
}
I want to query according to paymentMethod and eventId. So I was doing the following but it is not working.
db.Transaction.find({ "paymentMethod": "method1"});
and this is how I go all the transactions for "method1" but I am not sure on how should I query for eventId inside of related objects. I tried something like
db.Transaction.find({"paymentMethod": "method1", "relatedObjects[0].eventId" : "123131313131322" })
I didnt seem like it was going to work in my head but I have no clue on how to query an object inside an array.
Damn I had to read for third time the docs, sorry,
It was something like
{
"paymentMethod": "method1",
"relatedObjects" : {
$elemMatch : {
"eventId": "13213213212131321321"
}
}
}

How to update object in array, only if object property is equal to search term [duplicate]

This question already has answers here:
Update field in exact element array in MongoDB
(5 answers)
Closed 3 years ago.
Here is dummy JSON:
{
"_ID": ObjectId('xdfdsf'),
"array": [
{
"name": "Jon",
"permissions": [
"update",
"delete",
"create"
]
},
{
"name": "Ben",
"permissions":[
"update"
]
}
]
}
And so on. I want to create a query that will search the array, find element in array which has name "Ben" and pushes new permission into the array.
It's probably relatively simple to do but I got completely lost.
You can use $ positional operators to do such updates.
Try this :
db.collection_name.update({
"array.name" : "Ben"
},{
$push : {
"array.$.permissions" : "new_permission"
}
}
Read more about $(update) positional operator in official MongoDb docs for detailed information.
Sadly, Zoti's answer was incorrect, but I finally got it working:
db.myCollection.update( { "array.name": "Ben"}, {$push: {"array.$.permissions": "read"}})

Mongo query to fetch selective fields from the collection [duplicate]

This question already has answers here:
How to select a single field for all documents in a MongoDB collection?
(24 answers)
Closed 4 years ago.
Is it possible to fetch selective fields from mongo collections.
Say if my collections is
USer_info
{"_id" : ObjectId("56e0a3a2d59feaa43fba49d5", "date":"2018-07-23T00:00:00.000Z", "Name":"ABC", "ID": "1234", "Subjects":"[Maths, Physics, Science, Music]"}
{"_id" : ObjectId("56e0a3a2d5hjhfjtaese45d5", "date":"2018-07-23T00:00:00.000Z", "Name":"BCS", "ID": "3456", "Subjects":"[CS, Physics, Business]"}
{"_id" : ObjectId("56e0a3a2d59feaa43fba49d6", "date":"2018-07-23T00:00:00.000Z", "Name":"XYZ", "ID": "786", "Subjects": "[Agricultar, Business, Music]"}
Query to list only Name and SUbjects fields:
{"Name":"ABC", "Subjects":"[Maths, Physics, Science, Music]"}
{"Name":"BCS", "Subjects":"[CS, Physics, Business]"}
{"Name":"XYZ", "Subjects": "[Agricultar, Business, Music]"}
Not sure if this a duplicate, but i did not get anything similar so posting it.
You have to define projection part of .find() method to specify which fields should be returned. You alsow have to explicitly exclude _id, try:
col.find({}, { "_id": 0, "Name": 1, "Subjects": 1 })

How to join two collection in mongo without lookup

I have two collection, there name are post and comment.
The model structure is in the following.
I want to use aggregation query post and sort by comments like length sum, currently I can query a post comments like length sum in the following query statement.
My question is how can I query post and join comment collection in Mongo version 2.6. I know after Mongo 3.2 have a lookup function.
I want to query post collection and sort by foreign comments likes length. Is it have a best way to do this in mongo 2.6?
post
{
"_id": ObjectId("5a39e22c27308912334b4567"),
"uid": "0",
"content": "what is hello world mean?",
}
comment
/* 1 */
{
"_id": ObjectId("5a595d8c2703892c3d8b4567"),
"uid": "1",
"post_id": "5a39e22c27308912334b4567",
"comment": "hello world",
"like": [
"2"
]
}
/* 2 */
{
"_id": ObjectId("5a595d8c2703892c3d8b4512"),
"uid": "2",
"post_id": "5a39e22c27308912334b4567",
"comment": "hello stackoverflow",
"like": [
"1",
"2"
]
}
Query a post comments like sum
db.getCollection('comment').aggregate([
{
"$match": {
post_id: "5a39e22c27308912334b4567"
}
},
{
"$project": {
"likeLength": {
"$size": "$like"
},
"post_id": "$post_id"
}
},
{
"$group": {
_id: "$post_id",
"likeLengthSum": {
"$sum": "$likeLength"
}
}
}
])
There is no "best" way to query, as it'll really depend on your specific needs, but... you cannot perform a single query across multiple collections (aside from the $lookup aggregation pipeline function in later versions, as you already are aware).
You'll need to make multiple queries: one to your post collection, and one to your comment collection.
If you must perform a single query, then consider storing both types of documents in a single collection (with some identifier property to let you filter on either posts or comments, within your query).
There is no other way to join collections in the current MongoDB v6 without $lookup,
I can predict two reasons that causing you the issues,
The $lookup is slow and expensive - How to improve performance?
$lookup optimization:
Follow the guideline provided in the documentation
Use indexs:
You can use the index on the reference collection's fields, as per your sample data you can create an index for post_id field, an index for uid field, or a compound index for both the fields on the basis of your use cases
You can read more about How to Improve Performance with Indexes and Document Filters
db.comment.createIndex({ "post_id": -1 });
db.comment.createIndex({ "uid": -1 });
// or
db.comment.createIndex({ "post_id": -1, "uid": -1 });
Document Filters:
Use the $match, $limit, and $skip stages to restrict the documents that enter the pipeline
You can refer to the documentation for more detailed examples
{ $skip: 0 },
{ $limit: 10 } // as per your use case
Limit the $lookup result:
Try to limit the result of lookup by $limit stage,
Try to coordinate or balance with improved query and the UI/Use cases
You want to avoid $lookup - How to improve the collection schema to avoid $lookup?
Store the analytics/metrics:
If you are trying to get the total counts of the comments in a particular post then you must store the total count in the post collection whenever you get post get a new comment
{
"_id": ObjectId("5a39e22c27308912334b4567"),
"uid": "0",
"content": "what is hello world mean?",
// new fields
"total_comments": 10
}
Store minimum reference data:
If you want to show the comments of a particular post, you can limit the result for ex: show 5 comments per post
You can also store a max of 5 latest comments in the post collection to avoid the $lookup, whenever you get the latest comment then add it and just remove the oldest comment from 5 comments
{
"_id": ObjectId("5a39e22c27308912334b4567"),
"uid": "0",
"content": "what is hello world mean?",
// new fields
"total_comments": 10,
"comments": [
{
"_id": ObjectId("5a595d8c2703892c3d8b4567"),
"uid": "1",
"comment": "hello world"
},
{
"_id": ObjectId("5a595d8c2703892c3d8b4512"),
"uid": "2",
"comment": "hello stackoverflow"
}
]
}
Must read about Reduce $lookup Operations
Must read about Improve Your Schema

Mongo - request all embedded comments in Post query

I'm adapting the Microscope tutorial to my needs and am having difficulty writing a query which gathers all the comments embedded within a post.
Here is my query so far:
Posts.find({"postId": this._id}, {"comments":{}});
Here is an example post I want to get the comments from:
{
"_id": "Ad9RYqWqbsJKZx3h7",
"title": "Writing decimal number words as a decimal number",
"userId": "9yqTaFeQSqvKmNn8B",
"author": "Sacha Greif",
"submitted": "2017-01-05T03:26:18.908Z",
"commentsCount": 4,
"comments": [
{
"body": "Hello",
"postId": "Ad9RYqWqbsJKZx3h7",
"userId": "73qGvsRuqNtXcaZDx",
"author": "student",
"submitted": "2017-01-05T10:26:45.745Z"
},
{
"body": "How are you?",
"postId": "Ad9RYqWqbsJKZx3h7",
"userId": "73qGvsRuqNtXcaZDx",
"author": "student",
"submitted": "2017-01-05T10:28:17.225Z"
}
]}
It seems to return a cursor, but I am not able to use the toArray() function on it.
I have read this is not possible (Filtering embedded documents in MongoDB), but this was six years ago...
I've also seen posts about $slice and aggregate but can't seem to get me head around them.
Any help much appreciated!
query this->
Posts.find({"comments.postId": this._id});
You can just simply use findOne to get the specific document from the collection and you can use forEach Loop to iterate through the comments array of that document.
var post = Posts.findOne({_id: "<id_of_the_post>"});
var post_comments = post.comments; // post_comments contains the comments array
or if you want to do something with each comment use forEach
post_comments.forEach(function(entry, index, arr){
// entry has the comment object
//do something with the comment
});
I hope this helps.