Populate without _id - mongodb

I have 2 mongoose schemas, one for stock (info about stock) and one for trade. Where trade represents the trades of a stock (so time, volume, etc). Each stock has a symbol code and the data feed that I get the trades from includes the symbol codes as strings. How would I populate these two collections since I can't use the regular mongoose 'ref' here.
Here are my two schemas:
const stockSchema = new Schema({
symbolCode: { type: String, trim: true },
symbol: { type: String, trim: true },
type: { type: String, index: true, trim: true },
country: { type: String, lowercase: true }
})
const tradeSchema = new Schema({
symbolCode: { type: String, index: true },
symbol: { type: String, index: true },
price: Number,
volume: Number,
time: Date,
currency: { type: String, default: 'USD', uppercase: true, index: true }
})
I want to remove the first two fields in the trade schema so that I can just have some kind of reference to the stock here. How can I do this?

use the populate like this:
MyModel.populate([{ path: 'author', select: 'username name -_id' }]);
the -fieldName or in your case -_id will deduct it from the projection.

For future reference, I solved this using populate virtuals as follows:
stockSchema.virtual('trades', {
ref: 'Trade',
localField: 'symbolCode',
foreignField: 'symbolCode',
justOne: true
})

Related

Id is created for every nested objects in documents of a collection in mongodb via mongoose

I have a user schema. While saving document, for every nested object (quizHistory,record & responses) in document, mongoose add _id field automatically. For ref- quizHistory path
const userSchema = new Schema({
firstName: { type: String, required: true ,trim:true},
lastName:{ type: String, required: true ,trim:true},
email: { type: String, unique: true, required: true },
isUser: { type: Boolean, default: true },
password: String,
quizHistory: [{
quizId: { type: Schema.Types.ObjectId, ref: 'Quiz' },
record: [{
recordId:{ type: Number},
startTime: { type: Date },
responses: [{
quesId: { type: Schema.Types.ObjectId, ref: 'Question' },
answers: [Number]
}],
score: Number
}],
avgScore: Number
}]
})
Mongoose create virtual id by default(guide id).
Add this line to your schema.
_id : {id:false}

Products with different variants schema

I am trying to create an e-commerce website using MongoDB. I have created a Product and variant model, my question is how can I search the product with variant, for example for "Size" user can add variant value as "S" or "Small". How can I search the product which has for example small product in this case as a product have many variants, how can I list eg. all products with small size. Here is my variant model.
var variantSchema = Schema({
name: {
type: String,
required: true,
unique: true
},
count: {type: Number, default : 0}
});
And my Product Schema is:
var productSchema = Schema({
sku: {
type: String,
lowercase: true
}, //, required: true, unique: true
name: {
type: String,
lowercase: true,
max: 65,
required: true
},
slug: {
type: String,
lowercase: true,
unique: true,
index: true,
slug: "name",
slug_padding_size: 3
},
status: Boolean,
listPrice: Number,
description: {
short: {
type: String,
trim: true,
lowercase: true
},
long: {
type: String,
trim: true,
lowercase: true
}
},
images: [],
categoryId: {
type: Schema.Types.ObjectId,
ref: 'Category'
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date,
default: Date.now
},
isActive: Boolean,
vars: [
{
varId : {
type: Schema.Types.ObjectId,
ref: 'Variants'
},
values: [
{
value : String,
image:[]
}
]
}
]
});
Based on your comment.
You can distinguish "Small" and "small" by ignoring case sensitive.
UserModel.findOne({
email: {'$regex': "^"+ email +"$", $options:'i'}
}, function (err, data) {
callback(err, data)
});
But you can not match S with Small.
Approach 1:
You need to maintain the possible words that you want to consider as Small. Maybe by inserting in Variant Schema an array ["S", "Small"] like this. But in this scenario. You must have to caution about S. S can be anything. (I am not recommended this approach)
Approach 2:
I would like to suggest making one schema (SizeSchema) that can present the size. for e.g. Small, Large, Extra small, Extra Large etc... And reference that SizeSchema to VariantSchema and ProductSchema to VariantSchema. (Triple relationship). And this would be fixed for the end user. No one will have an option like "S".
Hope this may help you.

How join two collections in MongoDB using node js

I have searched for join two collection in MongoDB. I found populate. But it is not working for my scenario. I am using mongoose in node js. My schema are like below.
const CoordinateSchema = new mongoose.Schema({
activationId: {
type: mongoose.Schema.ObjectId,
ref: 'Activation'
},
mac: {
type: mongoose.SchemaTypes.String,
required: true,
set: toLower
},
t: { type: Date },
userId: {
type: mongoose.Schema.ObjectId,
ref: 'User'
}
});
const UserSchema = new mongoose.Schema({
email: {
type: mongoose.SchemaTypes.String,
required: true,
//unique: true,
set: toLower
},
mac: {
type: mongoose.SchemaTypes.String,
required: true,
unique: true,
set: toLower,
index: true
},
dob: {
type: mongoose.SchemaTypes.Date,
},
gender: { type: mongoose.SchemaTypes.String, set: toLower },
activations: [{
activationId: {
type: mongoose.Schema.ObjectId,
ref: 'Activation'
},
userType: { type: mongoose.SchemaTypes.String, set: toLower },
_id: false
}]
}
i have thousands of records for single activation in coordinates collection.
My query query requires to filter distinct mac from coordinates collection which matches userType in user collection.
If i use populate method & then apply filter on that it won't restrict fetching record count because of it query is taking so much time because it will return thousands of records.
I want to fetch only coordinates which match userType in user collection.
So far i haven't found any efficient method to join two collection & apply where condition on it.
I want to know efficient method to join two collection in mongodb & apply where condition on both collections.

Populate query with match returns null

I have three schemas, that need them to be separated and I can't use subdocuments. The important one is this
export var TestSchema = new mongoose.Schema({
hash: { type: String, index: { unique: true }, default: common.randomHash },
date: { type: Date, default: Date.now },
result: { type: Object },
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
data: { type: Object },
finished: Date,
lang: { type: String, default: 'pt' },
benchmark: { type: String, required: true },
order: { type: mongoose.Schema.Types.ObjectId, ref: 'Transaction' },
/* TODO: remove */
name: { type: String }
});
I have a query that does the populate (it's actually a pagination helper, but I'm cutting to the chase):
TestModel.find({hide: {$ne: true}, user: id}).populate({
path: 'user',
match: {$or: [
{email: new RegExp(search, i)},
{name: new RegExp(search, i)},
{empresa: new RegExp(search, i)},
]}
}).exec().then(/*...*/)
when populate.match doesn't find anything, it sets the user to null. I tried setting the find({'user':{$ne: null}}) but it ignores it. (I guess the populate happen after the find call, maybe that's the reason).
Is there any way I can filter it in the database layer instead having to rely on iterating of the results, check for null then filter out?
This answer on GitHub clarifies that it is not possible with populate, due to how MongoDB works. However, you should be able to do it with $lookup.

Moongose - how to customize a field in a scheme ? string and array in the same field

I would like to know how I can customize a field where you can use an array and string
eg:
var PostingSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
required: true,
trim: true
},
images: Array,
categorie: Array,
ubication:[{ type: Number, ref: 'Place'}],
agg:[{
agg :{ type: String, ref: 'Agg' },
value : String,
make :[{ type: Number, ref: 'Make'}]
}]
});
In the field agg value, I have a problem that can sometimes be of type string and sometimes can be of type array , should be of the array type I populate it with another scheme. How can I do that?
I made a field called "value ->string" and a "make->array" to do if there is a better way?