Related
hi i have this mongose models
new mongoose.Schema({
type_order: {
type: String,
required: true,
},
article: {
required: true,
type: [{
id: {type: mongoose.Schema.Types.ObjectId, ref: 'product'},
type_article: String,
quanty: Number,
}],
},
status: {
required: true,
type: String,
},
profile_id: {
required: true,
type: mongoose.Schema.Types.ObjectId,
ref: 'customer',
},
}, {timestamps: true});
module.exports = mongoose.model('order', dataSchema);
const dataSchema = new mongoose.Schema({
profile_id: {
type: String,
required: true,
},
title_lower: {
required: true,
type: String,
},
title: {
required: true,
type: String,
},
category_id: {
required: true,
type: String,
},
status: {
required: true,
type: String,
},
brand: {
required: true,
type: String,
},
description: {
required: true,
type: String,
},
stock: {
required: true,
type: Number,
},
price: {
required: true,
type: Number,
},
discount: {
required: true,
type: Number,
},
images: {
type: [{
url: String,
first: Boolean,
}],
},
}, {timestamps: true});
module.exports = mongoose.model('product', dataSchema);
I am trying to obtain the orders that have in their article field an article or several that belong to the profile id of the product that would be the person who published that product.
I am currently doing it bringing all the orders for the person's products but I know that it is not the most optimal way to do it and in the long run the performance will be affected.
i am trying something like this:
const profile = await customer.findOne({userId: req.user.id});
if (profile) {
// eslint-disable-next-line max-len
const articles = await Product.find({profile_id: profile._id});
const response=[];
const preresponse=[];
for (let index = 0; index < articles.length; index++) {
const element = articles[index];
const orders= await getOrdersByArticleId(element._id, res);
preresponse.push({
'article_id': element._id,
'title': element.title,
'price': element.price,
'stock': element.stock,
orders,
});
articles[index].orders = orders;
}
preresponse.forEach((art)=> {
art.orders.forEach((order)=>{
console.log(order);
const result = response.find(({order_id}) => order_id == order.order_id); ;
console.log(result);
if (result) {
console.log('holaa');
} else {
response.push({
'order_id': order.order_id,
'type': order.type_order,
'status': order.status,
'date': order.date.toDateString(),
'articles': [{'product_id': order.article_id,
'quanty': order.quanty}],
});
}
});
});
return res.status(200).json(articles);
}
I have two model one is productModel.js and another is reviewModel.js. I did child referencing in reviewSchema. product Schema has ratingsAverage and ratingsQuantity property. I want to manipulate these properties of properties inside from reviewModel.js. So that I have used statics method on reviewSchema.
reviewModel.js:
const Product = require("./productModel");
const { Schema } = require("mongoose");
const mongoose = require("mongoose");
const reviewSchema = new Schema({
review: {
type: String,
},
rating: {
type: Number,
min: 1,
max: 5,
},
createdAt: {
type: Date,
default: Date.now(),
},
product: {
type: mongoose.Schema.ObjectId,
ref: "Product",
required: [true, "A review must belong to a tour."],
},
user: {
type: mongoose.Schema.ObjectId,
ref: "User",
required: [true, "A review must belong to a user"],
},
});
// Preventing from duplication of review on same tour from same user
// Combined index
reviewSchema.index({ product: 1, user: 1 }, { unique: true });
// Creating calcAverageRating() static method for calculating average rating and number of ratings on product. It should work on creating, updating and deleting of review.
reviewSchema.statics.calcAverageRating = async function (productId) {
// "this" represents here model
const stats = await this.aggregate([
{
$match: { product: productId },
},
{
$group: {
_id: "$product",
nRating: { $sum: 1 },
avgRating: { $avg: "$rating" },
},
},
]);
console.log(stats, "rrrr");
// console.log(Product, "product");
// Problem is coming here i am not able to access productModel
// const doc = await Product.findByIdAndUpdate(
// productId,
// {
// ratingsAverage: stats[0],
// ratingsQuantity: stats[0],
// },
// {
// new: true,
// runValidators: true,
// }
// );
};
// As you know static methods only call on Model so we have to think about how to call calcAverageRating() static method. problem is that we have to get this product id which one is used to creating review so we only get this id on document middleware("post") for creating and for updating and deleting we will get from get from query middleware(/^findOne/).
// Document middleware("save")
reviewSchema.post("save", function () {
this.constructor.calcAverageRating(this.product);
});
reviewSchema.post(/^findOneAnd/, async function () {
// console.log(await this.findOne());
this.r = await this.clone().findOne();
console.log(this.r, "query");
console.log(Product, "testing");
});
reviewSchema.post(/^findOneAnd/, function () {
this.r.constructor.calcAverageRating(this.r.product);
});
// reviewSchema.pre(/^find/, function (next) {
// this.populate({
// path: "product",
// select: "name",
// });
// next();
// });
// CREATING MODEL
const Review = mongoose.model("Review", reviewSchema);
// We can call here static method but we will not get productId so we have to call this static method before creating of Model.
// Review.calcAverageRating();
// EXPORTING
module.exports = Review;
productModel.js:
const mongoose = require("mongoose");
const { Schema } = require("mongoose");
const Review = require("./reviewModel");
// CREATING SCHEMA
const productSchema = new Schema(
{
name: {
type: String,
required: [true, "Please enter product name"],
unique: true,
trim: true,
},
slug: String,
price: {
type: Number,
required: [true, "A product must have a price"],
maxlength: [8, "Price cannot exceeds 8 characters"],
},
priceDiscount: {
type: Number,
validate: {
validator: function (val) {
// this only points to current doc on NEW document creation
return val < this.price;
},
message: "Discount price ({VALUE}) should be below regular price",
},
},
stock: {
type: Number,
required: [true, "Please Enter product Stock"],
maxLength: [4, "Stock cannot exceed 4 characters"],
default: 1,
},
summary: {
type: String,
required: [true, "A product must have a summary"],
},
description: {
type: String,
required: [true, "A product have a description"],
},
images: [
{
public_id: {
type: String,
required: [true, "Images public id is required"],
},
url: {
type: String,
required: [true, "Images url is required"],
},
},
],
ratingsAverage: {
type: Number,
default: 0,
},
numOfReviews: {
type: Number,
default: 0,
},
reviews: [
{
user: {
type: mongoose.Schema.ObjectId,
ref: "User",
required: true,
},
name: {
type: String,
required: true,
},
rating: {
type: Number,
required: true,
},
comment: {
type: String,
required: true,
},
},
],
user: {
type: mongoose.Schema.ObjectId,
ref: "User",
required: true,
},
category: {
type: String,
required: [true, "A product must belong to a category"],
},
createdAt: {
type: Date,
default: Date.now(),
},
// ratingsAverage: {
// type: Number,
// default: 4.5,
// min: [1, "Rating must be above 1.0"],
// max: [5, "Rating must be below 5.0"],
// // Declaring custom function for do some opeartion from get value
// // set: (val) => Math.round(val * 10) / 10, // 4.666666, 46.6666, 47, 4.7
// set: (val) => Math.round(val * 10) / 10,
// },
// ratingsQuantity: {
// type: Number,
// default: 0,
// },
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
productSchema.index({ name: "text", description: "text" });
// VIRTUAL POPULATE
productSchema.virtual("reviews", {
ref: "Review",
foreignField: "product",
localField: "_id",
});
// CREATING MODEL
const Product = mongoose.model("Product", productSchema);
// EXPORTING
module.exports = Product;
I want to combine two schemas in realm db and perform operations on them, just like join in sql. But i don't know how to do it. I did not
List item
understand anything from the document. How can I do that?I have two schematics
const barkod = {
name: 'barkod',
properties: {
StokNo: { type: 'int', indexed: true },
Barkod: { type: 'string', indexed: true },
Birim: 'string',
BarkodTipi: 'string',
Aciklama: 'string?',
YStokNo: 'int'
}
// primaryKey: 'Barkod',
}
const stok = {
name: 'stok',
primaryKey: 'StokNo',
properties: {
StokNo: 'int',
StokAdi: { type: 'string', indexed: true },
StokKisaAdi: 'string',
StokKodu: 'string',
StokTanimi: 'string',
GrupKodu: 'string',
KdvOranP: { type: 'int', default: 0 },
KDVOranT: { type: 'int', default: 0 },
OzelKodu1: 'string',
OzelKodu2: 'string',
OzelKodu3: 'string'
}
}`enter code here`
and I want to join these two schemas
'SELECT Stok.StokAdi, Barkod, StokNo FROM ? AS Barkod JOIN ? AS Stok ON Barkod.StokNo = Stok.StokNo',
I found the solution to the problem. And this is how I did it. Hope it helps for those who have this problem.
const CarSchema = {
name: 'Car',
properties: {
make: 'string',
model: 'string',
miles: {type: 'int', default: 0},
},
};
const PersonSchema = {
name: 'Person',
properties: {
name: 'string',
birthday: 'date',
cars: 'Car[]',
// picture: 'data?' // optional property
},
};
const exp1 = () => {
var person;
Realm.open({schema: [CarSchema, PersonSchema]})
.then(realm => {
realm.write(() => {
person = realm.create('Person', {
name: 'ayşegül',
birthday: new Date(1995, 11, 25),
// cars: 'Car[]',
});
console.log(person.cars);
let carList = person.cars;
carList.push({make: 'Honda', model: 'model1', miles: 100});
carList.push({make: 'Toyota', model: 'model2', miles: 200});
console.log(person);
});
})
.catch(error => {
console.log(error);
});
};
I am trying to insert my nested object to Realm with To-One Relationships method, but I got an unexpected result where all value of my nested object is the same thing as the value from the first of my nested object that has been Relationship
This is my schema looks like
const PhotoSchema = {
name: 'CUSTOMER_PHOTOS',
properties: {
base64: 'string'
}
};
const TimeSchema = {
name: 'CUSTOMER_TIMES',
properties: {
warranty: 'float',
finish: 'float'
}
};
const MainSchema = {
name: 'CUSTOMERS',
primaryKey: 'id',
properties: {
id: 'int',
name: 'string',
photo: {type: 'CUSTOMER_PHOTOS'},
time: {type: 'CUSTOMER_TIMES'},
}
};
And try to insert some data like this
import Realm from 'realm';
Realm.open({
path: 'mydb.realm',
schema: [PhotoSchema, TimeSchema, MainSchema]
})
.then((realm) => {
realm.write(() => {
realm.create('CUSTOMERS', {
id: Date.now(),
name: 'John',
photo: {
base64: 'ImageBase64'
},
time: {
warranty: 31,
finish: 7
}
})
})
})
.catch((error) => {
console.error(error)
});
The process of inserting data is successfully BUT I got unexpected result when successfully get that data from Realm
Unexpected Result in console.log()
{
id: 1601335000882,
name: "John",
photo: {
base64: "ImageBase64"
},
// This value is the same as PhotoSchema
time: {
base64: "ImageBase64"
}
}
I want to the actual result like this
{
id: 1601335000882,
name: "John",
photo: {
base64: "ImageBase64"
},
time: {
warranty: 21
finish: 7
}
}
I there anything wrong with my code? The Documentation is not too detail about the method, the explanation and the example is just like one word
UPDATE:
I got an unexpected result only in the console.log() and if I try to access the property directly like MY_DATA.time.warranty the result is what I expected
The Answer is: No
To-One Relationships method is not only for one Schema, and Thanks to Angular San for showing an example of Inverse Relationships method.
Try Inverse Relationships
I got an expected result with Inverse Relationships method. In this method, you have to add one property that connected to Main Schema and I want to call this a combiner property
const PhotoSchema = {
name: 'CUSTOMER_PHOTOS',
properties: {
base64: 'string',
combiner: {type: 'linkingObjects', objectType: 'CUSTOMERS', property: 'photo'}
}
};
const TimeSchema = {
name: 'CUSTOMER_TIMES',
properties: {
warranty: 'float',
finish: 'float',
combiner: {type: 'linkingObjects', objectType: 'CUSTOMERS', property: 'time'}
}
};
const MainSchema = {
name: 'CUSTOMERS',
primaryKey: 'id',
properties: {
id: 'int',
name: 'string',
photo: 'CUSTOMER_PHOTOS',
time: 'CUSTOMER_TIMES',
}
};
I am trying to populate an array of id's from another collection
My JsonSchema looks like this:
{
version: 0,
type: "object",
properties: {
id: {
type: "string",
primary: true
},
// This is populated as expected
working: {
type: "array",
ref: "othercollection",
items: {
type: "string"
}
},
// This is where I am having problems
notWorking: {
type: "array",
items: {
type: "object",
properties: {
// This property is not being populated
problem: {
type: "array",
ref: "yetanothercollection",
items: {
type: "string"
}
}
}
}
}
}
}
From the docs at https://pubkey.github.io/rxdb/population.html I should be able to:
Example with nested reference
const myCollection = await myDatabase.collection({
name: 'human',
schema: {
version: 0,
type: 'object',
properties: {
name: {
type: 'string'
},
family: {
type: 'object',
properties: {
mother: {
type: 'string',
ref: 'human'
}
}
}
}
}
});
const mother = await myDocument.family.mother_;
console.dir(mother); //> RxDocument
Example with array
const myCollection = await myDatabase.collection({
name: 'human',
schema: {
version: 0,
type: 'object',
properties: {
name: {
type: 'string'
},
friends: {
type: 'array',
ref: 'human',
items: {
type: 'string'
}
}
}
}
});
//[insert other humans here]
await myCollection.insert({
name: 'Alice',
friends: [
'Bob',
'Carol',
'Dave'
]
});
const doc = await humansCollection.findOne('Alice').exec();
const friends = await myDocument.friends_;
console.dir(friends); //> Array.<RxDocument>
So my question is why can I not access myDocument.notWorking[0].problem_?
Here is a screenshot of the console that might give you a better understanding of my situation:
As you can see the ingredients property is not populated with the data from the ingredients collection (not in picture). The taxes property, however, is populated.
This is not possible unless you use OEM methods.
https://rxdb.info/orm.html
const heroes = await myDatabase.collection({
name: 'heroes',
schema: mySchema,
methods: {
whoAmI: function(otherId){
// Return the item with id `otherId` from the other collection here
return 'I am ' + this.name + '!!';
}
}
});
await heroes.insert({
name: 'Skeletor'
});
const doc = await heroes.findOne().exec();
console.log(doc.whoAmI());