How can I make my mongo update query the most efficient? - mongodb

I have a large test database I am using to test my queries, and I am wondering how I can possibly go about making this update query much more efficient as it is terrible right now. Here is what I have so far:
const query = {
username:"billyBob",
socialPlatform:"twitter",
userUrl:"www.whoami.com"
};
const updateDoc = {
$set: {
'posts.0.sentiment': 'positive'
}
}
db.socialContent.update(query, updateDoc);
Here is an example doc:
{
"_id" : ObjectId("1234567890"),
"socialPlatform" : "twitter",
"username" : "billyBob",
"userUrl" : "www.whoami.com",
"posts" : [
{
"location" : "USA",
"timezone" : "CST",
"sentiment" : "perplexed",
"tweetLink" : "https://www.tweetlink.com"
}
]
}
username billyBob has thousands of posts for this specific social platform.

Related

Query providing different results on Cosmos (vs Pure Mongo)

I have a Mongo collection which has this document structure:-
{
"_id" : ObjectId("5d5e5f1dfc325d4018302293"),
"status" : "PENDING",
"workflowJourney" : [
{
"_id" : ObjectId("5d5e5f1dfc325d401830229c"),
"workflowDate" : ISODate("2019-08-22T09:23:41.491Z"),
"workflowType" : "Email",
"workflowDescription" : "Email sent to Joe Bloggs",
"workflowRecipient" : {
"employeeNumber" : "12345",
"firstName" : "Joe",
"surname" : "Bloggs",
"emailAddress" : "joe.blogs#example.com"
},
"workflowSubject" : "Invoice Approval Required (2112)",
"workflowHtmlContent" : "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitiona..."
},
{
"_id" : ObjectId("5d5e5f1dfc325d401830229d"),
"workflowDate" : ISODate("2019-08-22T09:23:41.507Z"),
"workflowType" : "Email",
"workflowDescription" : "Email sent to Jane Bloggs",
"workflowRecipient" : {
"employeeNumber" : "56789",
"firstName" : "Jane",
"surname" : "Bloggs",
"emailAddress" : "jane.bloggs#example.com"
},
"workflowSubject" : "Invoice Approval Required (2112)",
"workflowHtmlContent" : "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitiona..."
}
],
"approvals" : [],
"__v" : 1
}
I'm trying to create a query which will get a single workflowJourney. At the point of executing the query, I will already know the _id of both the main document and the workflowJourney subdocument, so I could use either/both of of these in my query.
The issue is, for this development project we are using Azure Cosmos and the query that I would expect to work is giving strange results.
If I run this in pure Mongo:-
db.getCollection('Invoices').find(
{"workflowJourney._id": ObjectId("5d5e5fd907ba93320cc54198")},
{"workflowJourney.$": 1.0}
);
I get this nice result back:-
{
"_id" : ObjectId("5d5e5f1dfc325d4018302293"),
"workflowJourney" : [
{
"_id" : ObjectId("5d5e5f1dfc325d401830229d"),
"workflowDate" : ISODate("2019-08-22T09:23:41.507Z"),
"workflowType" : "Email",
"workflowDescription" : "Email sent to Jane Bloggs",
"workflowRecipient" : {
"employeeNumber" : "56789",
"firstName" : "Jane",
"surname" : "Bloggs",
"emailAddress" : "jane.bloggs#example.com"
},
"workflowSubject" : "Invoice Approval Required (2112)",
"workflowHtmlContent" : "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitiona..."
}
]
}
Running the same query in Azure Cosmos (database contains the same data), I get this:-
{
"_id" : ObjectId("5d5e5f1dfc325d4018302293"),
"workflowJourney" : [
{},
{}
]
}
So, no useful results. I know that Cosmos DB is more of a Mongo emulator rather than a pure implementation. But I guess what I am trying to achieve is a fairly common scenario; I wonder if anyone has any suggestions on how I could re-write my query to get the result I need?
Many thanks
Glen
Okay, so I've achieved what I need to do by doing the filtering from the Node level instead. I guess the filter queries are really designed for returning entire documents rather than filtering information from within a single document.
Example:-
router.get('/emailPreview/:invoiceId/:workflowJourneyItemId', (req, res, next) => {
Invoice.findOne({ "_id": req.params.invoiceId })
.then(invoice => {
if(invoice) {
const emailHtml = invoice.workflowJourney.filter((item) => {
return item.id === req.params.workflowJourneyItemId;
})[0].workflowHtmlContent;
res.status(200).set('Content-Type', 'text/plain').send(emailHtml);
} else {
res.status(404).json({ Error: 'Email not found'});
}
}).catch(err => {
res.status(404).json({ Error: 'Email not found'});
})
});

Access document directly by ID

I'm used to working with firebase where I can access a document directly by fetching data from the db like so.
db.collection('collectionName/documentID').get();
I can't seem to find any documentation regarding doing something similar in mongodb. Do I have to use a find query to grab data from a mongodb or have I missed something? Thanks
I'm thinking
const collection = db.collection('collectionName');
collection.findOne({_id: ObjectId('documentID'); });
Since mongo consolse is an interactive javascript shell, One way would be to create a method similar to this:
function collectionNameGet(idToFind) {
return db.collection.find({_id: idToFind });
}
In the mongo shell you can directly get it as below:
db.st4.find({"_id" : "1234"})
Result set:
{ "_id" : "1234", "raw" : { "meas" : { "meas1" : { "data" : "blabla" }, "mesa2" : { "data" : "foo" } } } }
Or by default mongo id as:
db.st1.find({"_id" : ObjectId("5c578d57ce9ba4a066ca2fa4")})
{ "_id" : ObjectId("5c578d57ce9ba4a066ca2fa4"), "name" : "Just a name", "users" : [ "user1", "user2" ] }
For display the result in pretty format
db.st1.find({"_id" : ObjectId("5c578d57ce9ba4a066ca2fa4")}).pretty()
Result set:
{
"_id" : ObjectId("5c578d57ce9ba4a066ca2fa4"),
"name" : "Just a name",
"users" : [
"user1",
"user2"
]
}
Here st4 is my collection name in the database test, so once you are on mongo shell do the below steps before above query:
use test
db.st1.insert({"name" : "Just a name", "users" : [ "user1", "user2" ] })
and then you can query by default _id generated mongo, you can simply make a query to get the recently added documents in the collection st1 as below:
db.st1.find().sort({_id:-1}).limit(1)
Hope this will help you out to do some basic query on mongo shell

What Firebase Database structure is more appropriate? SWIFT 4, FIREBASE 5.0.0

NOTE: Database = DB
NOTE: I'm using SWIFT 4 and Firebase 5.0.0
I am making a practice Instagram like project to practice using Firebase. I have tested the below 'DB 1' but then thought of 'DB 2' and was unsure about which one is more efficient and easier to code? The application is just supposed to upload a 'post' to a DB with 1 or 2 images. Thank you in advance!
EDIT:
Given that users would be able to see posts from people they follow and see posts from everyone on the search page. What would be an appropriate structure?
DB 1:
{
"user1" : {
"posts" : {
"post1" : {
"imgURL" : "https://firebasestorage.googleapis.com/v0/b/datamodel2-52bdf.appspot.com/o/l#gmail.com%2Fpost1%2F19B28DCA-9CD1-4079-BC75-AB2981A64CE3?alt=media&token=d984d2bd-698e-4cf4-8e42-36bf277850f2"
},
"post2" : {
"imgURL" : "https://firebasestorage.googleapis.com/v0/b/datamodel2-52bdf.appspot.com/o/l#gmail.com%2Fpost1%2F19B28DCA-9CD1-4079-BC75-AB2981A64CE3?alt=media&token=d984d2bd-698e-4cf4-8e42-36bf277850f2"
}
},
"userInfo" : {
"email" : "exmple#gmail.com",
}
},
"user2" : {
"posts" : "allposts",
"userInfo" : "email"
}
}
DB 2:
{
"UserPosts" : {
"User1ID" : {
"Post1" : {
"ImageURL1" : "URL"
}
}
},
"Users" : {
"User1ID" : {
"email" : "email"
},
"User2ID" : {
"email" : "email"
}
}
}

MongoDB update all subelements from subarray [duplicate]

This question already has answers here:
How to Update Multiple Array Elements in mongodb
(16 answers)
Closed 6 years ago.
I have a collection with a following schema:
{
"_id" : ObjectId("52dfba46daf02aa4630cf529"),
"hotelVenue" : {
"rooms" : [
{
"clientId" : "ROOM_1",
"roomName" : "Executive"
},
{
"clientId" : "ROOM_2",
"roomName" : "Premium"
}
]
}
},
{
"_id" : ObjectId("52dfc2f9daf02aa2632bc8af"),
"hotelVenue" : {
"rooms" : [
{
"clientId" : "ROOM_1",
"roomName" : "Studio Room"
},
{
"clientId" : "ROOM_2",
"roomName" : "Soho Suite"
},
{
"clientId" : "ROOM_3",
"roomName" : "Luxury Suite"
}
]
}
}
I need to genearate unique id for all the records -> subarray.
i.e., in the example there is rooms so for each and every room type, I need give a unique id basically using ObjectId().
Output should look something like the below, where roomId being generated.
{
"_id" : ObjectId("52dfba46daf02aa4630cf529"),
"hotelVenue" : {
"rooms" : [
{
"clientId" : "ROOM_1",
"roomName" : "Executive",
"roomId" : "56f8cb3f0c658b4bc26172342"
},
{
"clientId" : "ROOM_2",
"roomName" : "Premium",
"roomId" : "56f8cb3f0c658b4bc26176d4"
}
]
}
}
I have written this script where it gives the following error: Error: Line 9: Unexpected token +
db.venues.find().forEach(function(data)
{
data.hotelVenue.rooms.forEach(function(roomItem)
{
db.venues.update({_id:data._id,'data.hotelVenue.rooms.clientId' : roomItem.clientId},
{
$set:
{
'hotelVenue.rooms.'+roomItem.clientId+'.roomId' : ObjectId()
}
});
});
})
EDIT: This should do it in a more efficient manner by only saving each document once;
db.venues.
find({"hotelVenue.rooms": { $elemMatch: {roomId: {$exists: 0}}}}).
forEach(function(doc) {
doc.hotelVenue.rooms.forEach(function(room) {
if(!room.roomId) {
room.roomId = ObjectId();
}
});
db.venues.save(doc);
});
The find filters out only documents that are in need of updating. After that, it's just a matter of updating the document as needed and calling save.
Of course, backups are in order before running potentially destructive queries from random people on the Internet against your production data set.

meteor client find is not working due to $eq

I subscribed to my servers's publication as follows:
Template.observedQuestions.onCreated(function(){
var self = this;
self.autorun(function(){
self.subscribe('observedQuestionsFeed');
});
});
Now I need to fetch my data using helper function:
Template.observedQuestions.helpers({
observedQuestionsList : function(){
questions = Questions.find({
observedByUsers : {$exists: true,$elemMatch:{$eq:Meteor.userId()}}});
return questions;
}
});
but it does not work due to $eq being not recognised in minimongo.
How to solve it?
doc sample:
{
"_id" : "rP4JP8jkprwwi3ZCp",
"qUserId" : "NLLW3RBXqnbSGuZ3n",
"type" : "question",
"date" : ISODate("2016-02-13T11:23:10.845Z"),
"subject" : "test",
"question" : "test",
"replies" : [
{
"rID" : "LphcqKnkTHf25SCwq",
"rUserID" : "NLLW3RBXqnbSGuZ3n",
"date" : ISODate("2016-02-13T11:23:10.847Z"),
"answer" : "reply1."
},
{
"rID" : "HxaohnEgxwNJLtf2z",
"rUserID" : "NLLW3RBXqnbSGuZ22",
"date" : ISODate("2016-02-13T11:23:10.848Z"),
"answer" : "reply2"
}
],
"observedByUsers" : [ "Bi24LGozvtihxFrNe" ]
}
Judging from your sample Questions document, the field observedByUsers is a simple array which contains user IDs.
As a result, you could simply use the following query:
Questions.find({observedByUsers: Meteor.userId()});