Adding extra value at Model.create with Mongoose - node.js

I have a large array that comes in from an API that I'd like to store straight into MongoDB.
Model.create(largeArray) ... // many documents created
The problem is, I have one additional key:value pair that I need to set for all documents in that array. It's a user id, and many documents are created for a given user once per API call. So for a given Model.create call, the user id is the same for every doc in the array.
Without mapping over the array, is there an efficient way of adding a field with a consistent value? Something like Model.create(myLargeArray, {userId: someUserId}) would be ideal, but I know this isn't the case with the Mongoose API.
function addDocsForUser(largeArray, someUserId) {
// each element of largeArray needs to have `userId: someUserId` added to it
return Model.create(largeArray)
}

Related

findMany is not a function in MongoDB

I was making a commenting system on my website. I stored all the comment data in MongoDB and now I abviously need to access that data to print out the comments to a user. But, I see that there is no 'findMany' function for the collection object. I just need to get all the code in the collection in an array. findOne finds one document, then findMany should be there right? Is there any other such function in the collection object which can give me all the data in a collection of a database in MongoDB
Any help would be great!
You must use the find().toArray() method instead of findMany({ }) to get all the data there in the collection and to keep that data in an array. This will give you an array with all the data in the collection.

Why is data retrieved from Firestore returning empty array when there are subcollections present?

I am trying to retrieve data from my the my firestore database using angularfire2.
This is what my current database looks like. I have a users collection that contains the userId doc which binds the userDetails and userPosts together.
However when I query this collection, it returns an empty array in the console.
I am using a firebase function to retrieve the data.
Firebase Function Index.ts
export const getFeed = functions.https.onCall(async (req,res) =>{
const docs = await admin.firestore().collection('users').get()
return docs.docs.map(doc => {
return {
postID: doc.id,
...doc.data()
}
})
})
TS File
tabTwoFeedInit (){
const getFeed = this.aff.httpsCallable('getFeed')
this.ajax = getFeed({}).subscribe(data=> {
console.log(data)
this.posts = data
})
}
How can I retrieve data from this firebase database successfully?
Firestore reads are shallow, and so they won't return subcollections automatically. Thus, your get() will only return the document ID, since the document has no fields.
To return the subcollections of a document, you need to call the getCollections method on that document. This can only by done by the admin API, but that should be fine for you since you are running inside a cloud function. As the documentation notes, it is generally expected that collection names are predictable (as they appear to be in your case), but if they aren't, you might consider restructuring your data.
Why are shallow reads desirable? It makes it possible to avoid retrieving potentially large collections of information that might be associated with, say, a user, so you can structure data more naturally. Depending on the size of the data, its possible that a field that is a map might make more sense for userDetails (but a collection is probably the right thing for userPosts).
If you are just creating the cloud function to retrieve the posts from this structure. I would prefer to restructure the database a bit and just use Collection Group Query on client side (with no requirement of cloud functions) to pull the posts.
By restructuring I mean, you should store userID inside the documents of userPosts sub collection.
Then simply user Collection Group Query to retrieve post of specific users.
The syntax is of firebase javascript library. You can find it's equivalent of angularfire
let posts= db.collectionGroup('userPosts').where('userId', '==', 'some-user-id');
I also ran into the same problem but I solved it by adding a field to the particular document i am trying to retrieve.Sometimes the cause is because the documents you are trying to get has no field in it. What I mean is that a document must have a field before the server can recognize it as an existing document.
Possibly there may be no field in the document you are trying to retrieve which makes tye server say it is not existing and so will not be retrieved.
So if you run into this problem, then consider adding a field to that document before you can successfully retrieve it.

Generate a unique ObjectId for a collection

I would like to generate a unique ObjectId for a resource to give back clients with the nodejs mongodb driver.
IE:
var ObjectID = require('mongodb').ObjectID;
var objectId = new ObjectID();
Reading about an ObjectId it seems that there are some cases in which this id may not be unique. Even though this is extremely rare I still cannot take a chance on having a duplicate id.
Question #1, Using this driver is it possible (even though unlikely) to get a duplicate id doing this:
var objectId = new ObjectID();
Question #2 (if above is not 100% guarantee to give a unique id):
Does this driver guarantee that for a certain collection the ObjectId that is automatically created when a new document is inserted is unique? If yes, how? If yes, can I somehow duplicate that behavior when calling new ObjectID() myself without a collection?
If the driver or the mongo server ensures (100% of the time) that for a collection every new doc gets a unique id, I could always have a collection of just ids, then when generating a new, empty doc for that collection I would ensure I get a unique ObjectId. However seems like overkill to have another collection just to store ids.
That being said some might ask why not just generate the ObjectId in a collection and update that doc later with data. The answer is that in my case data may not ever come later and I don't want to implement logic to check for empty docs that only contain an id.
It's very unlikely that the same ObjectID will generate as mongo guarantees unique ID. objectID is created with a combination of two same values and two different values (unix epoch time, and a random value). However, in any case of a duplicate, you won't be allowed to insert a document as objectID acts as a primary key and insert function will return duplicate key error to your callback. Read more here. The same error is returned if mongo node native library creates a duplicate ObjectID.
UPDATE: again after reading the code base, if "hypothetically" the objectID that was generated by the library isn't unique, the answer is no. We are not ensured by the library that the id is unique, but we are ensured of a duplicate error doesn't matter who or what sent the id.
Here's the process:
1. generates ID
2. Sends straight to server.
3. Returns results.
Mongo isn't looping in nodeJS with existing ids because the library isn't storing it in cache. Read the code base for the library.

Retrieving _id from mongoose create

Been searching for an answer to, what I think, is a common question.
I'm using Mongoose and Step.js (for code control).
I'm iterating through a couple records, creating individual models and hoping to return the created IDs. This is for a RESTful service I'm implementing to bulk insert records. I didn't include all the parts that Step is doing.
Code looks roughly like this:
var group = this.group();
for (var i in records) {
model.create(records[i], group());
}
The group function is Step, waiting for all the records to save.
The problem is once each record is saved, I'm hoping that Mongoose will return the _id associated with each create. It's only returning a result of the record itself without the proper _id value.
I've attempted creating the ObjectId and saving the model, but that failed and isn't recommended by a lot of people in a number of forums.
Thanks.

Mongoose: Running a second query on the returned documents

Problem:
I have a 'Group' collection. Each group has an embedded document of 'Members'. I need to pull out a specific Member by their 'MemberID' and fetch all their details from the 'Users' collection. I would like to do this using the '.populate()' method but only need to populate that single member's record not all the members records.
So my query looks like this:
DB.model('groups')
.findById(groupID)
.populate('members._user')
.run(function(err, group){
// then loop over every member and return the one that matches
// the member id we require
});
This seems like a very inefficient way of doing things considering I only need the user details for one member in the group! I only have the memberID not the userID so this is the reason I am going to the members collection.
How can I extract a single member from the embedded 'members' document and populate it?
The populate function takes 3 parameters: path, fields and conditions. fields and conditions are applied when the referred document(s) is(are) populated via a separate call to model.find(...). Try passing to populate a valid mongodb condition that will only return members that you are interested in.

Resources