Performance on sorting by populated field using mongoose - mongodb

I have learned that it is not possible to sort by populated field in mongodb during querying. Suppose I have a schema like below, and I have 1 million data in record. And i only need to return 10 records for each query, depending of the column sorting (asc/desc) and page defined. What are the effective solution to this problem?
Simplify problem:
In the front end, I will have a data table with column firstname, lastname, test.columnA and test.columnB. Each of this column is sortable by user.
My initial solution was to query everything out in mongoose, flattening it to json and using javascript to reorder and finally response the final 10 data only. But this will have bad performance impact with increasing data set.
var testSchema = {
columnA: { type: String },
columnB: { type: String },
}
var UserSchema = {
firstname: { type: string },
lastname: { type: string },
test: {
type: ObjectId,
ref: 'Test'
}
}

Related

How to use Object type in mongose schema?

I am trying to store the amount of time an employee has worked in my MongoDB database, but not able to make a mongoose schema whose type will object.
The desired database should have a document like this:
{
name: 'name of employee',
report: {'01-01-2023':5hr, '02-01-202':7hr, '03-01-2023':8hrs}
}
This report will contain an object whose key will be a date and the value will be minutes or hours an employee has worked on that date.
how can I make a schema to achieve the desired goal, I have tried like this but did not work.
const UserSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
report: {
type: Object, // what should I write here
}
})

What's the best way to update a Map/Dictionary which is part of a MongoDb document?

I'm new to MongoDb so I'm not sure what's the best approach regarding the following:
I have a MongoDb document which contains multiple fields, including a map/dictionary.
e.g. -> priceHistogram:
rents {
_id:"1234",
city:"London",
currentPrice:"500",
priceHistogram: {"14-02-2021" : "500"}
}
I would like to update the currentPrice field with the latest price but also add to the price histogram taday's date and the price'; e.g. if today's price would be 600, I would like to obtain the following:
rents {
_id:"1234",
city:"London",
currentPrice:"600",
priceHistogram: {"14-02-2021" : "500", "20-02-2021" ": "600"}
}
What would be the most efficient MongoDb function/approach allowing me to achieve this (everything else remains the same - _id/city)?
Thank you
Not sure how your schema looks like, I will assume that the schema looks similar to:
const rentsSchema = mongoose.Schema(
{
city: { type: String, required: true },
currentPrice: {type: String},
priceHistogram: {type: Map, of:String}
}
)
const rents = mongoose.model('Rents', histSchema);
And the update:
rents.updateOne({city:"London"},{
currentPrice:"600",
"priceHistogram.24-02-2021": "600"
})
Since as I have understood Map is another way to add arbitrary properties.

MongoDB/Mongoose querying subdocuments and indexing

Ok, so I am new to MongoDB and the world of document based databases. I have stored in MongoDB a collection of profiles which has two subdocuments; 'Interest' and 'Country'. Below is schema information:
var Country = new mongoose.Schema({
name: String,
countryCode: String
});
var Interest = new mongoose.Schema({
label: {
type: String
}
});
var Profile = connection.model('profile', {
uid: {
type: String,
unique: true,
sparse: true
},
username: String
country: Country,
interests: [Interest],
member_since: Date
});
Let's say I want to be able to run a fast and efficient query such that I can select all of the users interested in 'music' and whose countryCode is 'AU' but done in an efficient way that doesn't scan all documents (I'm guessing I need an index?), how can I do this? Below is a sample profile as it appears in Compass:
_id:59d17efa3ed3a453e2b865f9
username:"Rudolph"
country:Object
name: "Australia"
countryCode:"AU"
_id:59d17efa3ed3a453e2b865fa
__v:0
interests:Object
label:Array
0:"music"
1:"film"
2:"dance"
member_since:2017-10-01 19:49:14.565

Associated Data Not Returned From Apollo to Client?

Here's relevant Apollo code. (Many database fields have been omitted to make it faster/easier to read this post.)
CONNECTORS
const userAccountsDataModel = db.define('userAccountsData', {
id: {type: Sequelize.STRING, primaryKey: true},
picture_medium: {type: Sequelize.STRING}
});
const associatesDataModel = db.define('associatesData', {
_id: {type: Sequelize.STRING, primaryKey: true},
first_name: {type: Sequelize.STRING},
last_name: {type: Sequelize.STRING},
userID: {type: Sequelize.STRING},
});
associatesDataModel.belongsTo(userAccountsDataModel, {foreignKey: 'userID'});
SCHEMA
type userAccountsData {
id: String
picture_medium: String
}
type associatesData {
_id: String
first_name: String
last_name: String
userID: String
userAccountsData: [userAccountsData]
}
QUERY
const GETONEASSOCIATE_QUERY = gql`
query getOneAssociate($_id: String!) {
getOneAssociate(_id: $_id) {
_id
first_name
last_name
userID
accountsData{
id
picture_medium
}
}
} `;
RESOLVER
getOneAssociate(_, args) {
console.log('in getOneAssociate');
var ret = connectors.associatesData.findAll({
where: args,
include: [connectors.userAccountsData],
logging: console.log
}).then((res) => res.map((item) => item.dataValues));
return ret;
},
Via Sequelize, the resolver generates the following SQL:
SELECT "associatesData"."_id",
"associatesData"."first_name",
"associatesData"."last_name",
"associatesData"."userID",
"userAccountsDatum"."id" AS "userAccountsDatum.id",
"userAccountsDatum"."picture_medium" AS "userAccountsDatum.picture_medium"
FROM "associatesDatas" AS "associatesData"
LEFT OUTER JOIN "userAccountsData" AS "userAccountsDatum"
ON "associatesData"."userID" = "userAccountsDatum"."id"
WHERE "associatesData"."_id" = '35';
When I run the above SQL in my SQL client, I can see that all the data sought is being returned, including the data from the related "userAccountsData" table.
However, when the data gets to my client code running in javascript the browser, the data from the related table is missing-- the object that should contain it is null.
What am I missing?
Thanks in advance to all for any info!
This turned out to be an anomaly with Sequelize's automatic pluralizing of table names.
By default, Sequelize automatically pluralizes table names. It is supposed to be possible to turn this behavior off by using Sequelize's freezeTableName property. However, per this Sequelize issue post, there are cases in which Sequelize ignores the freezeTableName property and pluralizes (and sometimes singularizes) the table names anyway.
After discovering this I was able to resolve the anomaly by pluralizing the relevant table name and going through all my Apollo code to update the references to this table so that they would be pluralized as well.

Is it possible to extract only embedded documents from a Model in Mongoose?

I'd like to run a query on a Model, but only return embedded documents where the query matches. Consider the following...
var EventSchema = new mongoose.Schema({
typ : { type: String },
meta : { type: String }
});
var DaySchema = new mongoose.Schema({
uid: mongoose.Schema.ObjectId,
events: [EventSchema],
dateR: { type: Date, 'default': Date.now }
});
function getem() {
DayModel.find({events.typ : 'magic'}, function(err, days) {
// magic. ideally this would return a list of events rather then days
});
}
That find operation will return a list of DayModel documents. But what I'd really like is a list of EventSchemas alone. Is this possible?
It's not possible to fetch the Event objects directly, but you can restrict which fields your query returns like this:
DayModel.find({events.typ : 'magic'}, ['events'], function(err, days) {
...
});
You will still need to loop through the results to extract the actual embedded fields from the documents returned by the query, however.