Massive.js selecting specific nested fields from document - node.js

I have the following document sturcture stored in a document table
{
firstname: '',
surname: '',
...
manager: {
firstname: '',
surname: ''
...
}
}
When selecting records with Massive.js i can limit the fields returned by providing an options object.
await dbConn.table.findDoc(criteriaObj, { fields: ['firstname', 'surname'] });
This works great for root fields, but for nested objects; consider the manager field above, Massive returns that field as a JSON string rather than a parsed object.
await dbConn.table.findDoc(criteriaObj, { fields: ['firstname', 'manager'] });
Which returns the following.
[{
firstname: 'bob',
manager: '{"firstname":"","surname":""}'
}]
I've trawled through Massive's documentation and not been able to find any reference to using this feature with nested fields.
Is this even possible? Ideally I'd like to craft an options object where i can request any number of fields from the root document but also select any subset of fields from nested objects within that document.
Any information would be greatly appreciated thanks.

Related

How to search through multiple documents having object as field value for a keyword using index "text" in MongoDB?

I want to search if a keyword present in any of the fields in documents. some field values are objects.so it is also needed to check whether the keyword present inside that object also.
so I came across the following solution.
collections: products(having companyId as foreign key), company
mongoQuery
db.products.aggregate([{$match:{$text:{$search:"hello"}}},{$lookup:{from:"companies",localField:"companyId",foreignField:"_id",as:"company"}},{$unwind:"$company"}])
result
`
[
{
_id: ObjectId("63832de4e9dbcd9b2942ded7"),
companyId: [ ObjectId("6383048ae9dbcd9b2942dece") ],
title: 'hello world',
imageUrl: 'https://drive.google.com/file/image',
company: {
_id: ObjectId("6383048ae9dbcd9b2942dece"),
name: 'name1',
url: 'name1.com'
}
}
]
`
But problem is that i have another document where 'company.name' having value "hello".By using above query it doesn't return the second document.How can i solve this problem?
$or is your correct approach: https://www.mongodb.com/docs/manual/reference/operator/query/or/
Just use it with .find as example links shows and you will get an array of documents.

Mongoose populate() returns the '_id' field of populated documents with "new ObjectId()"

So I'm trying to fetch a set of company member documents that correspond to a specific user, and populate the company field of each document in the process. The aim here is to get the _id and the name fields of each company document that corresponds to a company member. I've been successful in fetching the company member documents, however, the _id field of each populated company is returned together with the "new ObjectId()" constructor as shown below:
The company members: [
{
company: { _id: new ObjectId("6296180fj2a538be87f058f"), name: 'aaa' }
}
]
Of course, the desired outcome is to get only the _id content without the ObjectId() constructor. I've tried using the method suggested in the accepted answer of this StackOverflow post, however, I got the same results (meaning the ObjectId() constructor didn't go away):
// Fetch up to 10 company members and populate their companies.
let companyMembers = await CompanyMember.find({user: user_id}, {_id: 0, company: 1}).populate({
path: 'company',
match: { name: { $regex : new RegExp(company_name, "i") } },
select: { _id: {"$toString": "$_id"}, name: 1 }
}).limit(10).exec();
Have you tried lean() funtion ?

How to find an object inside an array inside a mongoose model?

I'm trying to query an object that's inside an item which is inside a mongoose model, when I'm trying to find that object with the find() method or _.find() method, I can't get access to the object for some reason and when I console.log() it, it gives me undefined or when I use array.filter() it gives me an empty array, which means the object that I'm trying to access does not meet the criteria that I give it in the lodash find method, but then when I look at my database I see that the object does actually have the properties to meet the criteria. So I don't know what I'm doing wrong, here's my code: as you can see I'm trying to get the information of the item that the user clicked on and want to see:
router.get("/:category/:itemId", (req, res) => {
console.log(req.params.itemId);
//gives the item id that the user clicked on
console.log(req.params.category);
//gives the name of category so I can find items inside it
Category.findOne({ name: req.params.category }, (err, category) => {
const items = category.items; //the array of items
console.log(items); //gives an array back
const item = _.find(items, { _id: req.params.itemId });
console.log(item); //gives the value of 'undefined' for whatever reason
});
});
The category Schema:
const catSchema = new mongoose.Schema({
name: {
type: String,
default: "Unlisted",
},
items: [
{
name: String,
price: Number,
description: String,
img: String,
dateAdded: Date,
lastUpdated: Date,
},
],
dateCreated: Date,
lastUpdate: Date,
});
well the answer is a little bit obvious, you are using MongoDB and in Mongo you have "_ID" you can use that "_ID" only with Mongoose! so you just have to remove the underscore and that is it! do it like this const item = _.find(items, { id: req.params.itemId });
hope you are doing better.
When I look at your Schema I see that the item field is an array of objects which doesn't have an _id inside so when you create a new instance of catShema it just generates an _id field for the new instance but not for each item inside the items array, just also enter the id of the item in question because according to my understanding, you must also have a model called items in your database
When you save these records in your database, you will generate an element with this structure
{
_id: String, // auto generated
name: String,
items: [ {"name1", "price1", "description1", "imgUrl1", "dateAdded1", "lastUpdated1"},{"name2", "price2", "description2", "imgUrl2", "dateAdded1", "lastUpdated2"}, ...],
dateCreated: Date,
lastUpdate: Date
}
Note : the code provided at the top is only an illustration of the object which will be registered in the database and not a valid code
Here you can notice that there is not a field called _id in the object sent inside the database.
My suggestion to solve this issue is
To create an additional field inside the items array called _id like :
{
...,
items: [
{
_id: {
type: String,
unique : true,
required: true // to make sure you will always have it when you create a new instance
},
...
... // the rest of fields of items
},
...
Now when you create a new instance make sure in the object you enter in the database the _id is recorded when you call the catInstance.save() so inside the catInstance object you have to add the current Id of the element to be able to filter using this field.
Hope my answer helped, if you have any additional questions, please let me know
Happy coding ...

How can I populate array of objects in mongoose?

My schema looks like:
const mock = new Schema({
category:...,
name:....,
doneBy: [{
type:mongoose.Schema.Types.ObjectId,
ref: 'User'
}]
})
Query: 'doneBy' property is an array of particular users who have done the task. When I console.log it prints only ids as "doneBy: [id1,id2,id3......]". Now I want to populate these ids to get the particular user's info. Please share the method.
You can populate it in your query like so:
mock.find({...}).populate('doneBy')
If you want to populate the users but only select certain fields (for example, the username):
mock.find({...}).populate({ path: 'doneBy', select: { username: 1 } }) // _id will also be returned by default

How to update an index with new variables in Elasticsearch?

I have an index 'user' which has a mapping with field of "first", "last", and "email". The fields with names get indexed at one point, and then the field with the email gets indexed at a separate point. I want these indices to have the same id though, corresponding to one user_id parameter. So something like this:
function indexName(client, id, name) {
return client.update({
index: 'user',
type: 'text',
id: id,
body: {
first: name.first
last: name.last
}
})
}
function indexEmail(client, id, email) {
return client.update({
index: 'user',
type: 'text',
id: id,
body: {
email: email
}
})
}
When running:
indexName(client, "Jon", "Snow").then(indexEmail(client, "jonsnow#gmail.com"))
I get an error message saying that the document has not been created yet. How do I account for a document with a variable number of fields? And how do I create the index if it has not been created and then subsequently update it as I go?
The function you are using, client.update, updates part of a document. What you actually needs is to first create the document using the client.create function.
To create and index, you need the indices.create function.
About the variable number of fields in a document type, it is not a problem because Elastic Search support dynamic mapping. However, it would be advisable to provide a mapping when creating the index, and try to stick to it. Elastic Search default mapping can create you problems later on, e.g. analyzing uuids or email addresses which then become difficult (or impossible) to search and match.

Resources