Nodejs-mongodb: Update document structure for all documents in a collection - node.js

I have a collection data which has around 300k entries and its document looks like
{
"_id" : ObjectId("5xxx85"),
"user_id" : "1",
"name" : "test",
"user_private" : "0"
}
now i want to update all the documents in this collection and new document will look like
{
"_id" : ObjectId("5xxx85"),
"rid" : "1",
"user_name" : "test",
"is_private" : "private",
"is_moderator" : "true",
"amount" : "11111"
}
i.e i need to add new fields, update field names and check if user_private = 0 then put is_private as private or else put is_private as not_private.
I am a bit new so I am not able to get how can i do this efficiently as entries are around 300k.
Please suggest some ways, pseudo code will be really helpful

To update a document a filter criteria. Check pseudo code below and follow link to read more.
You'll need to have an existing value for user_private
db.messages.updateMany([
{ "user_private" : 0 }, // filter.
{ $set: {
"user_private" : "private",
"is_moderator" : "true"
}
}, // update.
{
upsert: true
}
]);
upserts - Creates a new document if no documents match the filter or Updates documents that match the filter based on the filter and update parameters provided.

Related

How to add/update in array document with condition in mongoose

I need to perform the upsert operation. Below is my document structure.
I want to update the spin_details array when there is a match found with package_id but with two conditions i.e. user_id & spin_details.package_id.
If there is a match with user_id but there is no match with spin_details.package_id then some package information has to be pushed into the spin_details array. If there is no match with user_id(only) itself then it should be able to insert a new document.
{
"_id" : ObjectId("6234ffa6bd36b0e5a05ac913"),
"user_id" : ObjectId("6230e5e2b1530b407cedeb1d"),
"__v" : 0,
"is_active" : true,
"spin_details" : [
{
"package_id" : ObjectId("6230e5e2b1530b407cedeb9d"),
"spin_count" : 10,
"_id" : ObjectId("6234ffa6f390e1fafa8e215b")
},
{
"package_id" : ObjectId("6230e5e2b1530b407cedeb2a"),
"spin_count" : 25,
"_id" : ObjectId("6234ffa6f390e1fafa8e409b")
}
]
}
I can do this using multiple different queries and then based on the result value. How can I do this with a single mongoose query for this situation?

Count occurrence of id in a complex array of objects structure(mongodb)

I need to check the amount of occurrence for a specific product id in a high complexity array of objects structure.
I tried with the aggregation functionality of MongoDB, but I only got the occurrences per document rather than the occurrences cross all the documents. The data structure of each document looks like this:
{
"_id" : ObjectId("5c4d67905a07f5dec1fcc763"),
"updatedAt" : ISODate("2019-01-27T08:16:11.706Z"),
"createdAt" : ISODate("2019-01-27T08:10:56.553Z"),
"pickupTime" : ISODate("2019-01-27T08:20:00.000Z"),
"shop" : ObjectId("5c24b007b55ea3d7c599c95b"),
"owner" : ObjectId("5c242e361ee775cdd8b047b6"),
"total" : 350,
"status" : "completed",
"lineItems" : [
{
"product" : {
"options" : [],
"enabled" : false,
"description" : "",
"shop" : ObjectId("5c24b007b55ea3d7c599c95b"),
"price" : 350,
"name" : "Capuccino",
"createdAt" : ISODate("2019-01-01T21:56:31.928Z"),
"updatedAt" : ISODate("2019-01-08T12:14:53.322Z"),
"_id" : ObjectId("5c2be20f8e52115849726fdc")
},
"_id" : ObjectId("5c48efbc9efde32fab7ae47d"),
"status" : "pending",
"quantity" : 1,
"config" : []
}
],
"__v" : 0
}
As you can see each document is a order, each order has lineItems that is a array of objects that contain the quantity of the desired product, the status of the current product, some configuration and the product itself. The product field is a snapshot of the product in the moment of the order as they may be changed by the supplier (cost, name description, etc.)
I currently tried the next aggregate formula:
{
$group: {
_id: {
'product': '$lineItems.product._id'
},
count: {
$sum: 1
}
}
}
But only returns the the occurrences of a product in each order, rather than cross all the orders. I understood I need to use $reduce to reformat the data structure, but I couldn't find a way how to organice my current data structure in order to make it match. Also I got said that after counting per product I can use the $sort to put the highest values on the top and then limit the search to the amount of records to return
The desirable result is get the top 5 most sold products based on the orders data.
Thanks.

How do I query a quite deeply nested object in mongodb?

I have a collection with multiple documents with this format:
{
"id" : "65451735",
"recommendations" : [
{
"lastModifiedDate" : ISODate("2018-12-07T00:00:00.000Z"),
"products" : [
{
"productName" : "name1",
"productId" : "productid1"
},
{
"productName" : "name2",
"productId" : "productid1"
}
],
"recommendationsValueGlobal" : 0.0
}
]
}
I have with filter with "id" and "productId".
There's 2 issues regarding the productId:
1.- it can accept comma separated values of multiple product ids
2.- the productId is really deeply nested, I've never searched through an object this deep in the document. There can be multiple recommendations, and multiple products
I need to return all documents where id matches and only include any of the products that have the Ids given, all other should not be displayed.
I know how to search on nested object inside an array, but this is way too much, specially with comma separated values. Any suggestion?
EDIT: Also the Id is not unique and can be repeated in multiple documents

update array in mongoose which matches the condition

my schema looks like
{
qty:{
property1:{
//something
}
property2:[{
size:40,
color:"black",
enabled:"true"
}]
}
}
property 2 is array what i want to do is update those array object whose enabled is true in single query
I tried writing the following query
db.col.update({
"qty.property2.enabled" = "true"
}, {
"qty.property2.color" = "green"
}, callback)
but it is not working
error:
[main] Error: can't have . in field names [qty.pro.size]
db.col.update({"qty.property2.enabled":"true"},{$set: {'qty.property2.$.color': 'green'}}, {multi: true})
this is the way to update element inside array.
equal sign '=' cannot be used inside object
updating array is done using $
Alternative solution for multiple conditions:
db.foo.update({
_id:"i1",
replies: { $elemMatch:{
_id: "s2",
update_password: "abc"
}}
},
{
"$set" : {"replies.$.text" : "blah"}
}
);
Why
So I was looking for similar solution as this question, but in my case I needed array element to match multiple conditions and using currently provided answers resulted in changes to wrong fields.
If you need to match multiple fields, for example let say we have element like this:
{
"_id" : ObjectId("i1"),
"replies": [
{
"_id" : ObjectId("s1"),
"update_password": "abc",
"text": "some stuff"
},
{
"_id" : ObjectId("s2"),
"update_password": "abc",
"text": "some stuff"
}
]
}
Trying to do update by
db.foo.update({
_id:"i1",
"replies._id":"s2",
"replies.update_password": "abc"
},
{
"$set" : {"replies.$.text" : "blah"}
}
);
Would result in updating to field that only matches one condition, for example it would update s1 because it matches update_password condition, which is clearly wrong. I might have did something wrong, but $elemMatch solution solved any problems like that.
Suppose your documet looks like this.
{
"_id" : ObjectId("4f9808648859c65d"),
"array" : [
{"text" : "foo", "value" : 11},
{"text" : "foo", "value" : 22},
{"text" : "foobar", "value" : 33}
]
}
then your query will be
db.foo.update({"array.value" : 22}, {"$set" : {"array.$.text" : "blah"}})
where first curly brackets represents query criteria and second one sets the new value.

Querying a property that is in a deeply nested array

So I have this document within the course collection
{
"_id" : ObjectId("53580ff62e868947708073a9"),
"startDate" : ISODate("2014-04-23T19:08:32.401Z"),
"scoreId" : ObjectId("531f28fd495c533e5eaeb00b"),
"rewardId" : null,
"type" : "certificationCourse",
"description" : "This is a description",
"name" : "testingAutoSteps1",
"authorId" : ObjectId("532a121e518cf5402d5dc276"),
"steps" : [
{
"name" : "This is a step",
"description" : "This is a description",
"action" : "submitCategory",
"value" : "532368bc2ab8b9182716f339",
"statusId" : ObjectId("5357e26be86f746b68482c8a"),
"_id" : ObjectId("53580ff62e868947708073ac"),
"required" : true,
"quantity" : 1,
"userId" : [
ObjectId("53554b56e3a1e1dc17db903f")
]
},...
And I want to do is create a query that returns all courses that have a specific userId in the userId array that is in the steps array for a specific userId. I've tried using $elemMatch like so
Course.find({
"steps": {
"$elemMatch": {
"userId": {
"$elemMatch": "53554b56e3a1e1dc17db903f"
}
}
}
},
But It seems to be returning a empty document.
I think this will work for you, you have the syntax off a bit plus you need to use ObjectId():
db.Course.find({ steps : { $elemMatch: { userId:ObjectId("53554b56e3a1e1dc17db903f")} } })
The $elemMatch usage is not necessary unless you actually have compound sub-documents in that nested array element. And also is not necessary unless the value being referenced could possibly duplicate in another compound document.
Since this is an ObjectId we are talking about, then it's going to be unique, at least within this array. So just use the "dot-notation" form:
Course.find({
"steps.userId": ObjectId("53554b56e3a1e1dc17db903f")
},
Go back and look at the $elemMatch documentation. In this case, the direct "dot-notation" form is all you need

Resources