Hello I am wondering is it possible to get only one object of nested collection instead of whole object with nested collection of those objects which contains this object as a result of findOne query.
Let's say i have this model, Warrior model:
const classNameList = ['rogue', 'priest', 'warrior'];
const EquipmentSchema = new Schema({
weapon: String,
armor: String,
totalWeight: Number
});
const WarriorSchema = new Schema({
name: {
type: String,
required: true
},
class: {
type: String,
validate: {
validator: (value) => classNameList.includes(value),
message: 'This class does not exist!'
}
},
age: {
type: Number,
min: 18,
max: 1000,
required: true
},
weight: {
type: Number,
min: 18,
max: 150
},
equipments: [EquipmentSchema]
});
Then to find the only one equipment which total weight equals 12 I created this query :
const result = await Warrior.findOne({'equipments.totalWeight':12});
As a response of this query I am getting whole Warrior object with list of equipments but I only want to get this one Equipment which totalWeight equals 12. Is there any possibility to get only this one Equipment object via query?
I know that I can find this object with .find() method and assign it to the variable but it is not something what I am looking for.
Related
I'm trying to find the cleanest way to implement a filter to an array of objects depending on a string keyword. I need to return those objects whose only specific properties contains the string value.
Let's say I have the following array of objects:
const products = [
{
name: 'car',
price: 100,
image: 'someurl'
email: 'car#car.car'
available: true,
},
{
name: 'phone',
price: 200,
image: 'someurl'
email: 'phone#phone.phone'
available: false,
},
{
name: 'bottle',
price: 300,
image: 'someurl'
email: 'bottle#bottle.bottle'
available: true,
},
];
As mentioned here: Filter array of objects whose any properties contains a value
One of the cleanest way to match any value in an array of objects whose properties have different types would be:
function filterByValue(array, string) {
return array.filter(o =>
Object.keys(o).some(k => String(o[k]).toLowerCase().includes(string.toLowerCase())));
}
This filterByValue function will return those objects whose any properties match the string value.
However, I'd like to add some conditions, so it only iterates and look for some match at "name", "price" and "email" properties, not looking at "image" and "available" properties.
Make an array of the properties to look at, and look at them instead of using Object.keys.
const propsToCheck = ['name', 'price', 'email'];
function filterByValue(array, string) {
return array.filter(o =>
propsToCheck.some(k => String(o[k]).toLowerCase().includes(string.toLowerCase())
)
);
}
I have the following schema:
const SectionSchema = new Schema({
title: {
type: String,
required: true,
maxlength: 24
},
message: {
type: String,
required: true,
minlength: 64,
maxlength: 1024
},
state: {
type: String,
validate: v => {
console.log("> section validation test");
return false;
}
}
}, {_id: false});
const InstructionSchema = new Schema({
name: {
type: String,
required: true
},
columns: [[SectionSchema]]
});
For the sake of reordering and simplicity I keep sections in a nested array of columns.
My problem is that no validation of SectionSchema is being performed, when I save changes:
// Create
const doc = new Instruction();
doc.name = "Test";
await doc.save(); // Save ok
// Later
const doc = await Instruction.findOne({name: "Test"});
doc.columns = [
[
{title: "Section1", message: "This is section one in column one.", state: "something"},
{title: "Section2", message: "This is section two in column one.", state: "something"},
],
[
{title: "Section1", message: "This is section one in column two."},
{title: "Section2"},
]
];
await doc.save(); // Save ok (doesn't validate?)
doc.columns[0][0].message = ""; // Should fail validation
await doc.save(); // Success...
When setting columns the save is successful, that means no validation is being made, including builtin and custom validation for each SectionSchema in the column array.
If my assumptions are correct, this is because for mongoose the columns field is a mixed type. Mongoose docs doesn't even cover the topic of mixed types validation.
I have tried marking the paths as modified, but that doesn't make any difference:
doc.markModified('columns.0.0.state');
What is the solution to SectionSchema validating correctly in this case?
Hi everyone I have an array of objects with some populated fields. This is the schema of the product.
import mongoose, { Schema } from 'mongoose';
const productSchema = new mongoose.Schema(
{
name: String,
description: String,
sku: String,
barcode: String,
isActive: Boolean,
quantity: Number,
availability: String,
taxClass: [{ type: Schema.Types.ObjectId, ref: 'TaxClass' }],
images: [{ type: Schema.Types.ObjectId, ref: 'Image' }],
variants: [{ type: Schema.Types.ObjectId, ref: 'Variant' }],
tags: [{ type: Schema.Types.ObjectId, ref: 'Tag' }],
price: {
comparePrice: Number,
price: Number
},
seo: {
name: String,
keywords: [
{
name: String
}
],
description: String,
image: String
}
},
{ timestamps: true }
);
const Product = mongoose.model('Product', productSchema);
export default Product;
So i have a function and I want to return all the products with the variant color of green.
export const returnFilteredProducts = async (_, { filters = null, page = 1, limit = 20 }, context) => {
await jwtAuthentication.verifyTokenMiddleware(context);
try {
let searchQuery = {};
const products = await Product.find(searchQuery).populate(['variants', 'tags', 'images', 'taxClass']);
console.log(products.filter((item) => item.variants.filter((e) => e.color.indexOf('green') >= 0)));
return {
products
};
} catch (error) {
handleError(error);
}
};
The thing is that it does not return me the document with a variant color of green, instead it returns all the documents.
I am implementing a filtering system so I don't filter the products with in the frontend with redux.
Regarding the filtering method that is applied into the products array:
products.filter((item) => item.variants.filter((e) => e.color.indexOf('green') >= 0))
Inner call item.variants.filter() returns an array.
The outer call: products.filter() will include the product item, since the array will coerce into true, even when empty.
You can use method Array.some() for the inner call,
which will return a boolean true if at least one item (e) in item.variants
has the desired color.
This way you will filter-out all the product items that do-not contain the desired color in at least one element of the item.variants array.
I'm trying to remove an index from my mongoDB collection in node.js application using mongoose. I tried using model.collection.dropIndex("username") but it gives me an error UnhandledPromiseRejectionWarning: MongoError: index not found with name [username].
Here is my Schema
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
var userTable = new Schema({
firstname: { type: String, required: true },
lastname: { type: String, required: true },
username: { type: String },
salt: { type: String },
passwordHash: { type: String },
email: { type: String, unique: true, required: true },
sessionToken: { type: String },
dateCreated: { type: String, default: new Date().toString() },
loginHistory: [String]
});
module.exports = mongoose.model("userTable", userTable);
When I perform the query in mongo shell from the terminal using command db.usertable.find({}), I can see that the results still have username field. I also tried after removing the username field from schema file, but even that didn't help.
Thanks in advance.
This drops all the indexes of the collection except for the object id
db.collection.dropIndexs();
to delete a certain index
first type the command
db.collecction.getIndexes();
You will see something like above the in the red square is the index name .
db.collection.dropIndex( { "indexname": 1 } )
Creating an index using a unique name:
db.collection('users')
.createIndex(
{ email: 1 },
{ unique: true,
name: 'users.email.unique_index' }, // here we set index name
);
and then drop the index using it's name:
db.collection('users').dropIndex('users.email.unique_index');
I have an array of the form [{key: ..., type: ..., value: ...}] and want to store it in the fields field in the following schema:
var articleSchema = mongoose.Schema({
name: {
type: String,
unique: true,
required: true
},
updated: {
type: Date,
default: Date.now
},
pageviews: {
type: Number,
default: 0
},
fields: [{
key: String,
type: String,
value: String
}],
image: String
});
I am doing this as follows, my Javascript array referenced as keyValueObj
Article.findOneAndUpdate(
{ name: articleName },
{
fields: keyValueObj
},
{ upsert: true },
callback
);
However, all that is stored in the database in the fields field is an array of strings like this: ["[object Object]"]
How can I store my Javascript array so that it matches my mongoose schema correctly?
I was able to fix this using Molda's idea of using a separate schema.
The updated fields field in the articleSchema now looks like this:
fields: [{
type: Schema.Types.ObjectId,
ref: 'Field'
}]
I then converted the array to an array of schema objects, like this:
keyValueObj = keyValueObj.map(function(fieldObj){
return new Field({
key: fieldObj.key,
type: fieldObj.type,
value: fieldObj.value
});
});
I was then able to store keyValueObj the was doing it in the initial code.