I want to do crud operations on about 1000 documents.
using a loop and insert 1 by 1 is fine, but there is a better aka faster way?
like for example in Postgres I can use generate_series() for that purpose, and what about Mongo?
As prasad wrote in the comments above, you can use insertMany(). You would write a loop to generate the documents and store them in an array. Then you could pass that array of documents to db.collection.insertMany().
Another option would be to use bulkWrite. You could write a loop to generate an array of the operations you want to insert. For example:
[
{ insertOne: { "document": { "name": "Gal", "hobbies": ["reading", "gaming" ] } } },
{ insertOne: { "document": { "name": "Gal", "hobbies": ["reading", "gaming" ] } } },
...
]
Then you would pass that array to bulkWrite:
try {
db.characters.bulkWrite(myArray);
} catch (e) {
print(e);
}
Related
Suppose our document looks like this
{
a:1,
b:[
{c:120,d:100},
{c:121,d:110}
]
}
Now how could I upsert new objects in this array?
Suppose I want to perform update on the above document and add {c:200,d:120} to b so my expected result looks like this
{
a:1,
b:[
{c:120,d:100},
{c:121,d:110},
{c:200,d:120}
]
}
Also the update will of $inc, meaning suppose I want to increment d by 200 if c is present(lets say c is 200 and it is already present in the above document), if not present then I want to upsert the document itself.
Any help would be much appreciated.
It can be achieved using the $push update command.
db.<Collection-Name>.updateOne({"a": 1}, {"$push": {"b": {"c":200, "d":120}}})
Note: Use $addToSet if you don't want duplicates elements inside the array
UPDATE:
I don't think your precise requirement can't be achieved by a single command.
Your exact requirement can be achieved by the below script:
if (db.test9.findOne({"_id": ObjectId("5f19402abbc59a3864783fc7"), "b.c": 200}, {"_id": 1}) != null) {
db.test9.updateOne({
"_id": ObjectId("5f19402abbc59a3864783fc7"),
"b.c": 200,
}, {
"$set": {
"b.$.d": 120
}
})
} else {
db.test9.updateOne({
"_id": ObjectId("5f19402abbc59a3864783fc7"),
}, {
"$push": {
"b": {
"c":200, "d":120
}
}
});
}
Assuming we have a document in my MongoDB collection like the following:
{
"_id": "coffee",
"orders": [ "espresso", "cappuccino", "espresso", ... ],
}
How do I use a single update statement that ensures there are exactly say 2 espressos in this document, without knowing how many there are to begin with?
I know that using 2 consecutive statements I can do
db.test.update(
{ _id: "coffee" },
{ "$pull": { "orders": "espresso" } }
);
followed by
db.test.update(
{ "_id": "coffee" },
{ "$push": { "orders": { "$each": ["espresso", "espresso"] } } }
);
But when combining both into a single statement, MongoDB balks with an error 40, claiming Updating the path 'orders' would create a conflict at 'orders' (understandable enough - how does MongoDB what to do first?).
So, how can I do the above in a single statement? Please note that since I'll be using the above in the context of a larger unordered bulk operation, combining the above in an ordered bulk operation won't work.
Thanks for your help!
given a document structure as shown, where the trades array can have thousands of items... how on earth could one do a query that would verify that the sequence always has 'startTradeId' one number higher than the previous items 'endTradeId', all the way through the array? is this even possible?
{
"name": "STOCK",
"trades": [{
"endTradeId": 41306,
"startTradeId": 41302,
...
},
{
"endTradeId": 41301,
"startTradeId": 41297,
...
},
{
"endTradeId": 41296,
"startTradeId": 41240,
...
},
...
]
}
You can use $where operator like below :
db.your_collection.find( { $where : function(){ return "this.trades.startTradeId > this.trades.endTradeId" }});
Lets say I have a document like this
{ "_id" : ObjectId("544946347db27ca99e20a95f"), "name" : "Foo Bar",'firstName':"foo", "lastName":"bar" }
If I perform two separate updates like this
update({'_id':'544946347db27ca99e20a95f'},{$set:{'lastName':'BARBAR'}})
update({'_id':'544946347db27ca99e20a95f'},{$set:{'name':'Foo BARBAR'}})
Is it like two separate transactions or does it aggregate both of them and do a single write?
If I have to learn more about the internal workings, what should I be searching for?
Thank you for your help.
It is two different update operations.
In almost all MongoDB Operators you can use many fields. So the best way is:
db.collection.update({ '_id':'544946347db27ca99e20a95f'}, {
'$set': { 'lastName': 'BARBAR', 'name': 'Foo BARBAR' }
})
You can learn more about Operators in the official documentation. For example the $set operator has the following syntax:
{ $set: { <field1>: <value1>, ... } }
You may want to use the "Bulk" API and in this case rewrite your function so that the can take a bulk object argument.
var bulk = db.collection.initializeOrderedBulkOp();
function foo(bulk){
// do something
bulk.find({ "_id": "544946347db27ca99e20a95f" }).updateOne({
"$set": { "lastName": "BARBAR" }
// do another thing
});
}
function bar(bulk){
// do something
bulk.find({ "_id": "544946347db27ca99e20a95f" }).updateOne({
"$set": { "name": "Foo BARBAR" }
// do another thing
});
}
foo(bulk);
bar(bulk);
bulk.execute();
I have a MongoDB collection with data in the format of:
[
{
"data1":1,
"data2":2,
"data3":3,
"data4":4,
"horses":[
{
"opponent":{
"jockey":"MyFirstName MyLastName",
"name":"MyHorseName",
"age":4,
"sex":"g",
"scratched":"false",
"id":"1"
},
"id":"1"
},
{
"opponent":{
"jockey":"YourFirstName YourLastName",
"name":"YourHorseName",
"age":4,
"sex":"m",
"scratched":"false",
"id":"2"
},
"id":"2"
}
]
},
...
]
Executing the following query returns exactly what I need:
db.race_results.find({ "$and": [ { "horses":
{ "$elemMatch": { "$and": [
{ "opponent.name": "MyFirstName MyLastName" },
{ "opponent.jockey": "MyHorseName"}
] } }
}
]})
However, this query takes 0.5 seconds to execute with my collection (there are a lot of records).
I am trying to find out how to create an index on the horses.opponent.name field of the data. I have read the docs about multikey indexes (here), but I'm not sure if this is exactly what I need or not. What I need (I think) is an index on the array element of horses, but only the name and jockey fields. Is this possible?
Is there a way to create an index to make my specific query (the one above) any faster?
Any pointers would be greatly appreciated. I am fairly new to MongoDB, but learning fast!
The index to create is:
db.race_results.ensureIndex({"horses.opponent.name":1, "horses.opponent.jockey":1})
After creating this index, the query in your case should return number of scanned objects that is equal to the number of matched objects:
db.race_results.find( { horses: { $elemMatch: { "opponent.name": "MyHorseName", "opponent.jockey": "MyFirstName MyLastName" } } }
).explain()