Mapping other collection by same schema name on Mongoose - node.js

Engine Collection
var EngineSchema = new mongoose.Schema({
name: String,
GF2: String,
GF3: String,
GF4: String,
ll98: String,
ll01: String,
ll04: String
});
Oil Collection
var OilSchema = new mongoose.Schema({
name: String,
GF2: String,
GF3: String,
GF4: String,
ll98: String,
ll01: String,
ll04: String
});
I made simple
Engine DB
{ _id: 57d9604b7ecbc0029a3aad3c,
name: 'N54 B30A',
ll01: '1',
ll01fe: '1',
ll04: '1',
__v: 0 }
OilDB
[ { _id: 57d9614265e6c402a2c09990, name: 'EDGE', ll04: '1', __v: 0 },
{ _id: 57d98e12acc05505cfd15aae,
name: 'SYNTEC',
GF2: '1',
GF3: '1',
GF4: '1',
__v: 0 } ]
If I have the N54 B30A than It needs classification about ll98, ll01, ll04
EDGE Product only one about classification ll04
totally I choose the 'N54 B30A' that has ll04 classification so I want to appear something that has the ll04 classification
'N54 B30A' -> ll04
'EDGE' -> ll04
ll04 mapping?
Select N54 B30A -> appear EDGE
My Code Simple but It did't execute
Engine.findOne({name: 'N54 B30A'}, {_id: 0, name: 0, __v: 0}, function(err, engine) {
var result = Object.keys(engine.toObject());//[ 'll01', 'll01fe', 'll04' ]
Oil.findOne({result[2] : 1},function (err, oil) {
console.log(oil)
});
})
More Question
I want to search many kind atrribute(ll01, ll01fe, ll04) such as
findOne({$or:{ll01:1},{ll01le:1},{ll04:1}},function...)
but I don't know how to add one item like {ll01 : 1} than add {ll01le:1} and {ll04:1}
I tried coding
My Code
Engine.findOne({name: 'N54 B30A'}, {_id: 0, name: 0, __v: 0}, function (err, engine) {
var result = Object.keys(engine.toObject());//[ 'll01', 'll01fe', 'll04' ]
var Json = [];
result.forEach(function (item) {
var code = {};
code[item] =1;
Json.push(code);
});
console.log(Json);
Oil.find({$or: Json}, function (err, oil) {
console.log(oil)
});
})
I'm not useful javascript so I made by only my thinking. is this right?

You cannot assign a value to JSON as {result[2] : 1}. Change your code to this
Engine.findOne({name: 'N54 B30A'}, {_id: 0, name: 0, __v: 0}, function(err, engine) {
var result = Object.keys(engine.toObject());//[ 'll01', 'll01fe', 'll04' ]
var oilFindQuery = {};
oilFindQuery[result[2]] = 1;
//or query
var orQuery = [];
result.forEach(function (item) {
var queryItem = {};
queryItem[item] = 1
orQuery.push(queryItem);
});
//oilFindQuery = {$or: orQuery};
Oil.findOne(oilFindQuery, function (err, oil) {
console.log(oil)
});
})

Related

How do I display only part of the array after findOne in MongoDB?

Restaurants is a collection and has objects like below:
{
_id: new ObjectId("61723c7378b6d3a5a02d908e"),
name: 'The Blue Hotel',
location: 'Noon city, New York',
phoneNumber: '122-536-7890',
website: 'http://www.bluehotel.com',
priceRange: '$$$',
cuisines: [ 'Mexican', 'Italian' ],
overallRating: 0,
serviceOptions: { dineIn: true, takeOut: true, delivery: true },
reviews: [
{
_id: new ObjectId("61736a0f65b9931b9e428789"),
title: 'asd',
reviewer: 'khoh',
rating: 3,
dateOfReview: '5/12/2002',
review: 'hey'
},
_id: new ObjectId("61736a0f65b9931b9e428790"),
title: 'dom',
reviewer: 'firuu',
rating: 4,
dateOfReview: '25/1/2002',
review: ' bruh'
}
]
}
I am using the below code to find this object based on the review id provided
async get(reviewId) {
const restaurantsCollection = await restaurants();
reviewId = ObjectId(reviewId)
const r = await restaurantsCollection.findOne({reviews: {$elemMatch: {_id: reviewId}}})
return r
This returns the whole object from the restaurant collection, what do I do if I want only the review displayed whose id is provided in get(reviewID)
Output:
{
_id: new ObjectId("61736a0f65b9931b9e428790"),
title: 'dom',
reviewer: 'firuu',
rating: 4,
dateOfReview: '25/1/2002',
review: ' bruh'
}
With a projection, specify the fields to return
The following returns only the review whose id is provided in get(reviewID)
async get(reviewId) {
const restaurantsCollection = await restaurants();
reviewId = ObjectId(reviewId)
const r = await restaurantsCollection.findOne(
{ reviews: { $elemMatch: { _id: reviewId } } },
{ "reviews.$": 1 }
)
return r
}
Test Here
You can also use find instead of fineOne
Query
replace the ObjectId("61736a0f65b9931b9e428789") with reviewId
this will return the reviews that match the _id in an array
if you want to get the first only, in case there is always max 1
you can replace the last project with
{"$project": {"_id": 0, "review": {"$arrayElemAt": ["$reviews", 0]}}}
*not sure if this is what you need
Test code here
aggregate(
[{"$match": {"reviews._id": ObjectId("61736a0f65b9931b9e428789")}}
{"$set":
{"reviews":
{"$filter":
{"input": "$reviews",
"cond":
{"$eq": ["$$this._id", ObjectId("61736a0f65b9931b9e428789")]}}}}},
{"$project": {"_id": 0, "reviews": 1}}])
This might not be the correct answer of your question but you can try something like this.
const r = await restaurantsCollection.findOne({reviews: {$elemMatch: {_id: reviewId}}})?.reviews.find(review => review._id.equals(reviewId))

Id of object mus be removed based on matching req.params.id

router.delete('/shopping-cart/:id', (req, res) => {
let cart = new Cart(req.session.cart);
console.log(req.params.id);
console.log(cart.generateArray());
});
console.log will output the following result (req.params.id):
5c863cc8ee0819f989acf9c3
console.log will output the following result (cart.generateArray()):
[ { item:
{ _id: '5c863cc8ee0819f989acf9c3',
imagePath: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
title: 'Gothic Video',
description: 'Absolutely stunning',
price: 10,
__v: 0 },
image: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
qty: 1,
price: 10,
id: '5c863cc8ee0819f989acf9c3' } ]
So how do I loop through all the items and check if id matches the req.params.id. If that is the case, it should remove that object and then return an updated array on the client side.
let cards = [{
item: {
_id: '5c863cc8ee0819f989acf9c3',
imagePath: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
title: 'Gothic Video',
description: 'Absolutely stunning',
price: 10,
__v: 0,
},
image: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
qty: 1,
price: 10,
id: '5c863cc8ee0819f989acf9c3',
}]
cards.forEach(element => {
delete element.id
})
console.info(cards)
I assume that is coming from cart.generateArray()?
If so, you probably should do that inside the function in question, but if you can't, then just map the results to a new array:
let result = cart.generateArray().map(item => {
const {id, ...entry} = item;
// if you want to also remove _id from the inner item, you can do the same
return entry;
});
console.log(result); // will have entries w/o id in them.
If you're looking to remove the nested item object as well, it's the smae approach, though I'll change some words to improve readability.
let result = cart.generateArray().map(cartItem => {
const {id, item, ...entry} = cartItem;
// this will remove both the id and the item keys
return entry;
});
console.log(result); // will have entries w/o id in them.

Getting error during the time of inserting the query on database

I am Facing the error at the time of insert the query.
Error is "db.collection.insert is not a function"
My database schema is like this
'use strict';
var mongoose = require('mongoose');
//Schema
var ABCSchema = mongoose.Schema({
sequenceid: {
type: Number
},
A: {
type: Array,
default: []
},
B: {
type: Array,
default: []
},
C: {
type: Array,
default: []
},
D: {
type: Array,
default: []
}
});
var ABC = module.exports = mongoose.model('ABC', ABCSchema);
Now I want to enter the data which looks like this.
It's just a sample by which you people can understand that how I can Store the value.
{
"_id" : ObjectId("5a2e2eb9104cce1b58385620"),
"sequenceid": 1,
"A" : [
{
"apple" : "red",
"count" : 24
}
],
"B" : [],
"C" : [],
"D" : [],
"__v" : 0
}
Now what I am trying to code is like this
ABC.insert({'sequenceid': 1, 'A': {'apple': 'red', 'count': 24}}, function(error, data){
console.log(data);
});
As #Manjeet Thakur pointed out what you are trying to insert at "A" is and object and not an Array
Change it to array
{
"A": [{
"apple": "red",
"count": 24
}],
"sequenceid": 1
}
Also you need to instantiate your model and save it
var abc = new ABC({'sequenceid': 1, 'A': [{'apple': 'red', 'count': 24}]});
abc.save()
//or
ABC.create({'sequenceid': 1, 'A': [{'apple': 'red', 'count': 24}]}, function (err, small) {
//if (err) return throw err;
// saved!
})
'use strict';
var mongoose = require('mongoose');
//Schema
var ABCSchema = mongoose.Schema({
sequenceid: {
type: Number
},
A: {
type: Array,
default: []
},
B: {
type: Array,
default: []
},
C: {
type: Array,
default: []
},
D: {
type: Array,
default: []
}
});
var ABC = module.exports = mongoose.model('ABC', ABCSchema);
// here now collection is ABC (name of collection)
ABC.insert({'sequenceid': 1, 'A': [{'apple': 'red', 'count': 24}] }, function(error, data){
console.log(data);
});

MongoDB/Mongoose geoNear returns incorrect distance

When I attempt to find a document with defined geo coordinates using the geoNear() method, MongoDB's calculation of the distance appears to be off, resulting in an empty array of results.
I have the following document in my locations collection:
{
"_id" : ObjectId("56e4791244ea3215c8537425"),
"name" : "Cool Place",
"address" : "224 West 71th Street, New York, NY 10023",
"rating" : 5,
"facilities" : [...etc...],
"coords" : [
-73.983342,
40.778183
],
"openingTimes" : [...etc...],
"reviews" : [...etc...]
}
My schema looks like this:
var locationSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
address: String,
rating: {
type: Number,
'default': 0,
min: 0,
max: 5
},
facilities: [String],
coords: {
type: [Number],
index: '2dsphere'
},
openingTimes: [openingTimeSchema],
reviews: [reviewSchema]
});
The relevant parts of my controller look like this:
var theEarth = (function () {
var earthRadius = 6371; // km, miles is 3959
var getDistanceFromRads = function (rads) {
return parseFloat(rads * earthRadius);
};
var getRadsFromDistance = function (distance) {
return parseFloat(distance / earthRadius);
};
return {
getDistanceFromRads: getDistanceFromRads,
getRadsFromDistance: getRadsFromDistance
};
})();
var buildResultsList = function (results) {
var resultsList = [];
results.forEach(function (doc) {
resultsList.push({
distance: theEarth.getDistanceFromRads(doc.dis),
name: doc.obj.name,
address: doc.obj.address,
rating: doc.obj.rating,
facilities: doc.obj.facilities,
coords: doc.obj.coords,
_id: doc.obj._id
});
});
return resultsList;
};
module.exports.locationsListByDistance = function (req, res) {
var lng = parseFloat(req.query.lng);
var lat = parseFloat(req.query.lat);
var maxDistance = parseFloat(req.query.maxDistance);
var point = {
type: 'Point',
coordinates: [lng, lat]
};
var geoOptions = {
spherical: true,
maxDistance: theEarth.getRadsFromDistance(maxDistance),
num: 10
};
Loc.geoNear(point, geoOptions, function (err, results, stats) {
sendJsonResponse(res, 200, buildResultsList(results));
});
};
Finally, this is the request that I'm making:
http://localhost:3000/api/locations?lng=-73.9827568&lat=40.7791425&maxDistance=10
However, I am only getting an empty array of results, even though the location is within 10km of the coordinates I specified in my request. If I change the maxDistance query param to 100000, the result is returned, showing a distance of 749557.1657218104 km:
[{"distance":749557.1657218104,"name":"Cool Place","address":"224 West 71th Street, New York, NY 10023","rating":5,"facilities":["Hot drinks","Premium wifi"],"coords":[-73.983342,40.778183],"_id":"56e4791244ea3215c8537425"}]
I used http://www.movable-type.co.uk/scripts/latlong.html to calculate the distance between these two sets of coordinates, and saw that they are only 0.1175 km apart.
Another note: if I use the exact coordinates associated with the location (-73.983342, 40.778183) in my query, the location IS returned, with the correct distance of 0 km.
Successful request:
http://localhost:3000/api/locations?lng=-73.983342&lat=40.778183&maxDistance=10
Returns:
[{"distance":0,"name":"Cool Place","address":"224 West 71th Street, New York, NY 10023","rating":5,"facilities":["Hot drinks","Premium wifi"],"_id":"56e4791244ea3215c8537425"}]
Any ideas what I'm doing wrong here? Thank you!
What version of Mongoose do you use? Try to use "mongoose": "~3.8.20" and update the npm package and try again.

Populate model of model on mongoose

I've been digging into this for a while now, found no answer valid and nothing like I want to do on Google so I've come here to ask this question.
How do you populate a Schema like this?
var category_schema = new mongoose.Schema({
name: {required: true, type: String},
parent: {type: Number, ref: 'Category' },
categories: [ {type: Number, ref: 'Category'} ]
});
What I'm doing right now is this:
Category.find({parent: null}).populate({path: 'categories', model: 'Category'}).exec(function(err, categories) {
But doing a console.log on categories would show on the console:
[ { __v: 2,
_id: 18,
name: 'Categoria',
parent: null,
categories:
[ { __v: 1,
_id: 19,
name: 'Children',
parent: 18,
categories: [Object] }, // <= THIS SHOULD HAVE ACTUAL CATEGORIES
{ _id: 20, name: 'Children 2', parent: 18, __v: 0, categories: [] } ] } ]
Any kind of help would be much appreciated.
Thanks.
Edit:
This is what I'm using to show em up
ul.list-group
if inputs == true
li.list-group-item
.radio
label
input(type='radio', class='radio', name='parent_id' value='0')
= 'No category'
mixin make_list(categories, edit)
each category in categories
li.list-group-item
.radio
if inputs == true
input(type='radio', name='parent_id', value='#{category._id}')
= category.name
if categories.length
each category in categories
li.list-group-item
.radio
label
if inputs == true
input(type='radio', name='parent_id', value='#{category._id}')
= category.name
if category.categories.length
ul
+make_list(category.categories, edit)
Since I had no answers, I started digging by myself on how to do this...
Now, this might not be the best way to do it, but oh well;
category_schema.static('make_tree', function(callback) {
Category.find(function(err, categories) {
var parents_array = [];
for(var i = 0; i < categories.length; i++) {
var category = categories[i];
if (category.parent == null || category.categories.length) {
categories[i].categories = [];
parents_array.push(categories[i]);
}
}
for(var x = parents_array.length -1; x >= 0; x--) {
for(var y = 0; y < categories.length; y++) {
if (categories[y].parent === parents_array[x]._id) {
console.log('adding ' + categories[y].name + ' to ' + parents_array[x].name);
parents_array[x].categories.push(categories[y]);
}
}
}
console.log(parents_array);
// Remove parents which have parents.
for(var i = parents_array.length - 1; i >= 0; i--) {
if (parents_array[i].parent) {
parents_array.splice(i, 1);
}
}
callback(parents_array);
});
});
Thing is..., I still get this when I do a console log:
PARENTS ARRAY NOW
[ { __v: 1,
_id: 23,
name: 'Categoria',
parent: null,
categories: [ { parent: 23, name: 'Hijo', _id: 24, __v: 2, categories: [Object] } ] } ]
I think you might be experiencing a vagary of the node console. What happens if you do console.log(categories[0].categories)? (assuming categories is the name of that fisrt object.

Resources