node.js how to find a document inside Inner Mongodb - javascript

Please teach me how to find a document inside Inner Mongodb. I'd like to bring you some coordinates inside the market. What should I do?
/**
* 데이터베이스 스키마를 정의하는 모듈
*
* #date 2016-11-10
* #author Mike
*/
//var crypto = require('crypto');
var Schema = {};
Schema.createSchema = function(mongoose) {
// 스키마 정의
var ItemSchema = mongoose.Schema({
itemName : {type: String, index: 'hashed', 'default':''}
,market : {
marketName: {type: String, index: 'hashed', 'default':''}
, marketId: {type: String, required: true, 'default':''} //마켓 고유번호
, geometry: {
type: {type:String, default:'Point'},
coordinates: [{type:'Number'}]
}
, tel: {type: String, required: true, 'default':''}
, address: { data: Buffer, contentType: String,default:'' }
}
,price : { type: 'Number',default:''}
,disPrice: {type: 'Number',default:''}
,count: {type: 'Number',default:''}
,expireTime : {type: Date, index: {unique: false} }
});
console.log('ItemSchema 정의함.');
ItemSchema.index({geometry:'2dsphere'});
ItemSchema.static('findNear',function(longitude,latitude,maxDistance,callback){
console.log('findNear 호출됨')
this.find().where('geometry').near({
center:{
type:'Point',
coordinates:[parseFloat(longitude),parseFloat(latitude)]
},
maxDistance:maxDistance
}).exec(callback);
});
return ItemSchema;
};
// module.exports에 UserSchema 객체 직접 할당
module.exports = Schema;
this is router
var findNearItem = function(req, res) {
console.log(' findNearData.');
var paramLongitude = req.body.longitude || req.query.longitude;
var paramLatitude = req.body.latitude || req.query.latitude;
var maxDistance = 10000;
var database = req.app.get('database');
database.ItemModel.findNear(paramLongitude, paramLatitude, maxDistance, function(err, results) {
if(err) {
console.dir(err);
return;
}
console.log('결과 -> ' + JSON.stringify(results));
var context = {
results:results
};
var output = JSON.stringify(context);
res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
res.write(output);
res.end();
});
};
this is config
{file:'./item',path:'/process/findNearItem',method:'findNearItem',type:'post'}

The find query return the whole record document, even if the query condition checking on an attribute in the sub document of the record like coordinates but in your case you want to return just the coordinates sub document.
I suggest using aggregate.
this.aggregate(
[{
$group: {
_id:"$market.geometry.coordinates"
}
}])
If you want to have the max value of coordinates in a maxDistance field
db.getCollection('market').aggregate(
[{
$group: {
_id:"$market.geometry.coordinates"
}},{
$project: { maxDistance: { $max: "$_id" }} //_id here is refering to "market.geometry.coordinates"
}])
Pipeline builder technique within schema static method:
ItemSchema.static('findNear',function(longitude,latitude,maxDistance,callback){
console.log('findNear 호출됨');
return this.aggregate().group({
_id:"$market.geometry.coordinates"
}).project({
maxDistance: { $max: "$_id" }
}).exec(callback);
});

sorry I can't use aggregate, I solved the problem by modifying the ItemSchema .
var ItemSchema = mongoose.Schema({
itemName : {type: String, index: 'hashed', 'default':''}
, marketName: {type: String, index: 'hashed', 'default':''}
, marketId: {type: String, required: true, 'default':''} //마켓 고유번호
, geometry: {
type: {type:String, default:'Point'},
coordinates: [{type:'Number'}]
}
, tel: {type: String, required: true, 'default':''}
, address: { data: Buffer, contentType: String,default:'' }
,price : { type: 'Number',default:''}
,disPrice: {type: 'Number',default:''}
,count: {type: 'Number',default:''}
,expireTime : {type: Date, index: {unique: false} }
});

Related

Creating a nested mongodb document using Apollo-graphql and mongoose

I am trying to create a restaurant mobile app using react native and for that I have used the following restaurant mongo model schema in the backend:
const restaurantSchema = mongoose.Schema({
uid: {type: String, default:uuid.v4,required: true, unique: true},
id: {type: String, unique: true},
name: {type: String, required: true, unique: true},
phone: {type: String, required: true, unique: true},
owner: {type: String, required: true},
address: {type: String, required: true, unique: true},
menu: [{
uid: {type: String, default:uuid.v4, unique: true},
id: {type: String, unique: true},
category_name: {type: String, unique: true},
subcategory: [{
uid: {type: String, default:uuid.v4, unique: true},
id: {type: String, unique: true},
subcategory_name: {type: String, unique: true},
item: [{
uid: {type: String, default:uuid.v4, unique:true},
item_name: {type: String, unique: true},
calories: {type: String},
type: {type: String, enum: ['VEGAN', 'VEG', 'NON_VEG']},
price: {type: String},
}]
}]
}]
},
{timestamps: true}
)
I want to run a mutation such that, starting with the category_name array, it should check for each of the subarrays that whether the specified entry already exists or not in a single flow
If for the category already exists then the mutation should check whether the subcategory exists or not and if the category or the sub-category doesn't exist, the resolver should create new entries.
The mutation I wrote is working for some parts like when I try to mutate twice, it creates a category and subcategory entry but not in a single mutation operation
My resolver-
addMenuItems: async(_, {menuItemInput:{restaurant_name,name,calories,type,price,category,subcategory}},context) => {
const user = await Auth.verifyToken(context,process.env.TOKEN_SECRET)
//console.log(String(user.id))
if (!user) {
throw new ApolloError('Session expired')
}
const present_user = await User.findOne({uid:user.id})
const valid_user = Rest.owner_checker(present_user.username,User)
if (!valid_user) {
throw new ApolloError('Only the owner is permitted to modify menu items!')
}
duplicate_item = Rest.duplicate_checker(name,restaurant_name,category,subcategory,Restaurant)
if (duplicate_item !== null) {
throw new UserInputError("This item already exists")
}
try {
const newMenuItemStatus = await Rest.Item_adder(Restaurant, [name,restaurant_name,calories,type,price,category,subcategory])
if (newMenuItemStatus === 'SUCCESS') {
console.log('New Item was added successfully')
const newMenuItem = await Restaurant.findOne(({name: restaurant_name},
{"menu":
{category_name: category,
"subcategory":
{"item": {
"$elemMatch": {"item_name": {"$in": name}}
}}
},
}))
return {
id: newMenuItem.id,
...newMenuItem._doc
}
}
} catch (error) {
throw new UserInputError('Item addition failed')
}
}
The mutation code:
static Item_adder = async (Restaurant, Payload) => {
const [name, restaurant_name,calories, type, price, category, subcategory] = Payload
const Restaurant_category = await Restaurant.findOne({name: restaurant_name,
"menu": {
"$elemMatch": {"category_name": {"$in": category}}}}
)
console.log("Abefore: ",Restaurant_category)
if (Restaurant_category == null) {
await Restaurant.updateOne(
{name: restaurant_name},
{"$push": {"menu": {category_name: category}}},
function (error, res) {
if (error) {
console.log(error)
}
else {
}
}
)
}
const Restaurant_subcategory = await Restaurant.findOne({name: restaurant_name,
"menu.subcategory": {
"$elemMatch": {"subcategory_name": {"$in": subcategory}}}}
)
console.log("B: ",Restaurant_subcategory)
if (Restaurant_subcategory == null) {
await Restaurant.updateOne(
{name: restaurant_name,
"menu": {category_name: category,
"$push": {"subcategory": {subcategory_name: subcategory}}}
},
function (error, res) {
if (error) {
console.log(error)
}
else {
console.log(res)
}
})
}
await Restaurant.updateOne({name: restaurant_name,
"menu":
{category_name: category,
"subcategory":
{subcategory_name: subcategory,
"$push": {"item": {item_name:name,
calories:calories,
type:type,
price:price}}}
},
function (error, res) {
if (error) {
console.log(error)
}
else {
console.log(res)
}
}
})
return 'SUCCESS'
}
Where am I going wrong? I tried several combinations of resolvers and mongoose update queries but I've got no luck so far.

Adding Array To Mongo via AJAX Call and Mongoose

I'm trying to update a document in a mongo database with information from a form, with all the form going into a field which is an array. At the moment I can't get it to update a document, only create a new one, but more pressingly I can't get the information from the form into the array.
Here is my schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const WorkoutSchema = new Schema({
day: {
type: Date,
default: Date.now
},
exercises: [
{
type: String,
trim: true,
required: "Exercise type is required"
},
{
name: String,
trim: true,
required: "Exercise name is required"
},
{
duration: Number
},
{
weight: Number
},
{
reps: Number
},
{
sets: Number
},
{
duration: Number
},
{
distance: Number
}
]
});
const Workout = mongoose.model("Workout", WorkoutSchema);
module.exports = Workout;
And here is my API route. I've included the results of console.logs below it so you can see the information that is getting passed.
app.put("/api/workouts/:id", (req, res) => {
console.log("api body: " + JSON.stringify(req.body));
console.log("body is " + typeof req.body);
var body = JSON.stringify(req.body);
// body = body.split("{")[1];
// body = body.split("}")[0];
// body = "["+body+"]";
console.log(body);
Workout.create({exercises: `${body}`})
.then(Workout => {
res.json(Workout);
})
.catch(err => {
res.json(err);
});
});
api body: {"type":"resistance","name":"Test Press","weight":100,"sets":5,"reps":6,"duration":10}
body is object
{"type":"resistance","name":"Test Press","weight":100,"sets":5,"reps":6,"duration":10}
In the database I get exercises as an array with one element - the above object - instead of a series of key/value pairs. I've tried a lot of things, but this is as close as I get to what I'm trying to do.
Can anyone see where I've gone wrong?
This turned out to be a basic syntax error which came about because one of my keys was "type". The issue is in the syntax of the exercises array, the model should look like this:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const WorkoutSchema = new Schema({
day: {
type: Date,
default: Date.now
},
exercises: [{
type: {
type: String,
trim: true,
required: "Exercise type is required"
},
name: {
type: String,
trim: true,
required: "Exercise name is required"
},
duration: {
type: Number,
required: "Duration is required"
},
weight: {
type: Number
},
reps: {
type: Number
},
sets: {
type: Number
},
distance: {
type: Number
}
}]
});
const Workout = mongoose.model("Workout", WorkoutSchema);
module.exports = Workout;

Mongoose: Trying to retrieve a document with (id) - getting NULL

So I am trying to retrieve a course using its id. I've tried using:
Course.findOne({ _id: __id })
Course.findById(id)
I not sure why it's not working, do I have to define _id type in the schema?
Result:
null
Here is my schema + function
const courseSchema = new mongoose.Schema({
name: { type: String, required: true, minlength: 3, max: 255 },
category: {
type: String,
required: true,
enum: ["web", "mobile", "network"]
},
tag: [String],
data: Date,
author: String,
isPublished: Boolean,
price: {
type: Number,
required: function() {
return this.isPublished;
},
min: 10,
max: 200
},
__v: Number
});
const Course = mongoose.model("Course", courseSchema);
async function updateCourse(id) {
// var __id = mongoose.Types.ObjectId(id); // tried converting string id (?)
console.log(id);
// // method 1
const course = await Course.findOne({ _id: __id });
console.log("resulting...", course);
if (!course) return;
course.isPublished = true;
course.author = "Another author";
const result = await course.save();
console.log("saved....", result);
}
updateCourse("5c726f6feb352743f8226239");
MongoDB:
You should not use __id in your Course.findOne call - use _id: _id:
Course.findOne({_id: _id});
Try to replace __id with id.
Course.findOne({_id: id});

Delete only those, which have no Entry in first table corresponding to the second table

var productSchema = Schema({
product_code: String,
name: {
type: String,
required: true
},
description: String,
category:{
type: String,
ref: 'Product_Category'
},
umo: String,
threshold: {
type:Number,
default: 0
},
image: String,
isactive: {
type: Boolean,
default: true
}
});
var product_categorySchema = Schema({
isactive: {
type: Boolean,
default: true
},
name: {
type: String,
required: true
},
description: String
});
I have these two schema I am deleting from category, but if I have data corresponding to that category in product table then that category should not be deleted. Can anyone help?
it should look like something like this :
// Function which delete the category behind the given _id
async function deleteCategory(idCategory) {
// check if there is a product related to the category
const ret = await product_schema.findOne({
category: idCategory,
});
// if there is, return an error
if (ret) throw new Error('Cannot delete the category');
// else do delete the category
return product_category_schema.remove({
_id: idCategory,
});
}
Also you have to know that :
category:{
type: String,
ref: 'Product_Category'
},
is not the right way to setup a reference; it should be an ObjectId not a String
const {
Schema,
} = mongoose;
category:{
type: Schema.Types.ObjectId,
ref: 'Product_Category'
},
Firstly, please update "type" property of "category" field in product schema like this:
category:{
type: Schema.Types.ObjectId,
ref: 'Category' // model name
}`
and declare model like this :
var Product = mongoose.model('Product', productSchema );
then use "distinct" query and "$nin" query-operator to delete category which are not referenced by product schema like this :
Product.find().distinct('category').then((data)=>{
Category.deleteMany({_id: {$nin: data}}).then(del => {
console.log("deleted",del)
})
})

node.js api with array's

I'm pretty new to node.js and javascript. I'm builded and api and out of the sudden the data model changed and now i'm kinda lost.
This is my code:
var mongoose = require('mongoose');
//create schema
var MedicSchema = new mongoose.Schema({
nombre:{
type: String,
required: true
},
especialidad:{
type: String,
required: true
},
ranking:{
type: Number,
},
direccion: [{
direccion: {type: String, required: true},
telefono: {type: String},
horario:{type: String}
}],
foto:{
type: String,
}
});
MedicSchema.find({})
.populate('direccion')
.exec(function (err, medic) {
console.log(medic.direccion); // This should have your information now
});
//export model
module.exports = MedicSchema;
I'm able to send data to the direccion array... but when i call the api; i get this:
{
"_id": "557839b36bcdd00e09173e36",
"nombre": "Sra. Hong",
"especialidad": "general",
"__v": 0,
"direccion": [
{
"_id": "55a44392b2e774572b957a8e"
},
{
"_id": "55a44392b2e774572b957a8d"
}
]
}
i can't find a way to call the details of the array.
edit: i posted it on bitbucket https://bitbucket.org/weput/api-server
You need to .populate your "direccion" array. For example:
MedicSchema.find({})
.populate('direccion')
.exec(function (err, medic) {
console.log(medic.direccion); // This should have your information now
});

Categories

Resources