Mongoose Querying Sub-Document Properties - node.js

I am trying to expose this functionality through a WEB API. The way it is set up in this code is that someone does a GET on URL providing a querystring along with it in the form of:
?field=value&anotherfield.subproperty=value
But I can't seem to get querying based on sub-document properties to work. Below you will find my barebones code, record I'm trying to receive and both of my test cases.
Code:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var config = require('../config');
var User = require('../models/user');
var functions = require('../functions');
router.get('/', function(req,res,next) {
//Check Permissions associated with UID *TODO
var parameters = req.query;
console.log(parameters);
User.find(parameters, function(err, users) {
if (err)
{
json = functions.generateOperationOutcome("exception","error",err,"exception");
res.status(500);
res.json(json);
}
else
{
//Check for blank result
if (users.length === 0)
{
json = functions.generateOperationOutcome("not-found","warning","Non-Existent Resource","warning");
res.status(404);
res.json(json);
}
else {
res.status(200);
res.json(users);
}
}
});
});
Record:
{
"_id": "5871d2e814946a941d8611fb",
"resourceType": "testResource",
"link": [],
"communication": [],
"animal": {
"genderStatus": {
"coding": []
},
"breed": {
"coding": []
},
"species": {
"coding": []
}
},
"contact": [],
"photo": [],
"maritalStatus": {
"coding": []
},
"address": [],
"gender": "unknown",
"telecom": [
{
"system": "phone",
"value": "2019196553",
"use": "home"
}
],
"name": {
"suffix": [],
"prefix": [],
"given": [],
"family": []
},
"identifier": [
{
"use": "official",
"type": {
"coding": {
"system": "kylec laptop",
"version": "0.01",
"code": "UDI",
"display": "Universal Device Identifier",
"userSelected": false
},
"text": "test"
},
"system": "test system",
"value": "test value",
"assigner": {
"reference": "test assigner reference"
},
"period": {
"start": "1992-12-31T09:59:59+00:00"
}
}
]
}
Successful Query:
GET http://{{LOCAL}}/api/user?resourceType=testResource
Returns this one model from MongoDB.
Unsuccessful Query (no documents matching query found):
GET http://{{LOCAL}}/api/user?telecom.system=phone
Returns no models back and results in a 404.

You are not properly using dot-notation, as the property you're seeking is within an array:
"telecom": [
{
"system": "phone",
"value": "2019196553",
"use": "home"
}
]
Querying array content typically would require you to do a join against the array (for DocumentDB queries), and not a simple find().
If you wanted the ability to use dot-notation here, you'd need to create a subdocument, like:
"telecom": {
"system": "phone",
"value": "2019196553",
"use": "home"
}
At this point, you'd be able to address properties such as telecom.system, telecom.value, and telecom.use.

Related

How to get multiple association results in sequelize

i have problem fetching the association results.
I have two models
1 - User
2 - Project
User.hasMany(Project, { foreignKey : 'user_Id' });
Project.belongsTo(User, { foreignKey: { name: 'user_Id', type: DataTypes.UUID } })
when i fetch data through Project Model then corresponding user info is also fetched.
getAllProjects: async (req, res) => {
const projects = await Project.findAll({ include: User});
res.json({projects})
}
Result of above code
results
{
"projects": [
{
"id": "9bb3b99c-ac14-48fa-a0f2-e707f1d517ad",
"name": "this is project name",
"budget": "$34",
"details": null,
"days": null,
"deadline": null,
"user_Id": "02ef60af-0b1e-45e9-b393-55e124673143",
"start_date": null,
"status": 0,
"createdAt": "2022-03-23T03:02:56.000Z",
"updatedAt": "2022-03-23T03:02:56.000Z",
"User": {
"id": "02ef60af-0b1e-45e9-b393-55e124673143",
"name": null,
"email": null,
"password": null,
"userType": "client",
"createdAt": "2022-03-23T03:02:35.000Z",
"updatedAt": "2022-03-23T03:02:35.000Z"
}
}
]
}
But in reverse when i try to fetch user with their projects, user info is fetched but the associated projects are not fetched.
Code
getAllUsers: async (req, res) => {
const users = await User.findAll({inlcude: [{model: Project}]})
res.json({users})
}
** Result of above code**
{
"users": [
{
"id": "02ef60af-0b1e-45e9-b393-55e124673143",
"name": null,
"email": null,
"password": null,
"userType": "client",
"createdAt": "2022-03-23T03:02:35.000Z",
"updatedAt": "2022-03-23T03:02:35.000Z"
}
]
}
Please help me. Thanks in advance.
Simply correct typo from inlcude to include.
const users = await User.findAll({include: [{model: Project}]})

Mongoose/MongoDB PUT: Push Object to Array if Object ID is unique within Array

I want to update an array within a document, only if the object being pushed to the "items" array has a unique id within the "items" array.
{
"_id": "6039e37cb6b60f4694a16705",
"list_name": "Example Picklist",
"author_id": "6027f627141a75567cc2e0b0",
"author_name": "Test",
"items": [
{
"upcs": [
"111222333"
],
"qty": 10,
"id": "123456",
"name": "Item A"
},
{
"upcs": [
"444555666"
],
"qty": 22,
"name": "Item B",
"id": "987654"
}
],
"status": "initialized",
"__v": 0
}
For example, I should be able to add:
{
"name": "Item C",
"qty": 99,
"upcs": ["111555999"],
"id": "111111"
}
but not:
{
"name": "Item C",
"qty": 99,
"upcs": ["111555999"],
"id": "123456"
}
My put request is currently not refusing req.bodys with already existing ids, after I tried implementing JohnnyHK's answer to this question.
router.put('/:id', auth, async (req, res) => {
const item = req.body; // insert above examples
try {
let picklist = await Picklist.findById(req.params.id);
if (!picklist)
return res.status(404).json({ json: 'Picklist not found' });
picklist = await Picklist.findByIdAndUpdate(
{ _id: req.params.id, 'items.id': { $ne: item.id } },
{
$push: { items: item },
},
{ new: true }
);
res.json(picklist);
} catch (err) {
console.error(err.message);
res.status(500).json({ msg: 'Server Error' });
}
});
What am I getting wrong? At the moment it will push anything that fits with the Schema, and doesn't stop ID duplicates.
The error is that I was using
Picklist.findByIdAndUpdate()
instead of
Picklist.findOneAndUpdate()

Resolving the OverwriteModelError in mongoose

Hi I wrote a Lambda function using nodejs to retrieve the data's from mongodb and it works fine. Later I use the API to produce link and to view the output in that link. Now the output is showed in console but in that API it showing OverwriteModel Error.I attached my code and output in API. What shall I do now ?
const mongoose = require('mongoose')
const models=()=>{
mongoose.connect('---',{useNewUrlParser:true,useCreateIndex:true,useUnifiedTopology:true})
const wavicle = mongoose.model('Datasetlist',{Dataset:[{id:Number,dataset:String,parameter:
{name:String}]}]})
const me = wavicle.find({})
return me
}
const main = async(event)=>{
console.log('EVENT:',event)
return models()
}
exports.handler = main
CONSOLE OUTPUT:
[
{
"_id": "5f05714c96db3e0007ae3595",
"Dataset": [
{
"parameter": [
{
"_id": "5f05714c96db3e0007ae3597",
"name": "StoreName"
},
{
"_id": "5f05714c96db3e0007ae3598",
"name": "Dates"
},
{
"_id": "5f05714c96db3e0007ae3599",
"name": "TransDesc"
},
{
"_id": "5f05714c96db3e0007ae359a",
"name": "Amount"
},
{
"_id": "5f05714c96db3e0007ae359b",
"name": "credit"
},
{
"_id": "5f05714c96db3e0007ae359c",
"name": "total"
}
],
"_id": "5f05714c96db3e0007ae3596",
"id": 1,
"dataset": "Daily Food Report"
}
],
"__v": 0
}
]
API OUTPUT:
{
"errorType": "OverwriteModelError",
"errorMessage": "Cannot overwrite `Datasetlist` model once compiled.",
"trace": [
"OverwriteModelError: Cannot overwrite `Datasetlist` model once compiled.",
" at Mongoose.model (/var/task/node_modules/mongoose/lib/index.js:524:13)",
" at models (/var/task/index.js:7:26)",
" at Runtime.main [as handler] (/var/task/index.js:18:12)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
"errorType": "OverwriteModelError" signifies that you are over writting Datasetlist model
which already exist in your database under different Schema or same name like DataSetlist or DATASETLIST or dataSetlist .
First delete previous model.
Then run your code ,this time it will create new model without any error
I'm defining the mongodb connection and creating mongoose model inside the models function so every time it creating the mongoose model with same name and same schema repeatedly and overwriting so it's shows the error "overwritemodelerror". Now I had kept the mongoose model and mongodb connection part outside the models function
const mongoose = require('mongoose')
mongoose.connect('mongodb+srv://Sethu16:Sethu16##samplecluster.xtrb0.mongodb.net/Wavicle?retryWrites=true&w=majority',{useNewUrlParser:true,useCreateIndex:true,useUnifiedTopology:true})
const Wavicle = mongoose.model('Datasetlist',{Dataset:[{id:Number,dataset:String,parameter:[{name:String}]}]})
const models=()=>{
const me = Wavicle.find({})
return me
}
const main = async(event)=>{
console.log('EVENT:',event)
return models()
}
exports.handler = main
CONSOLE OUTPUT:
[
{
"_id": "5f05714c96db3e0007ae3595",
"Dataset": [
{
"parameter": [
{
"_id": "5f05714c96db3e0007ae3597",
"name": "StoreName"
},
{
"_id": "5f05714c96db3e0007ae3598",
"name": "Dates"
},
{
"_id": "5f05714c96db3e0007ae3599",
"name": "TransDesc"
},
{
"_id": "5f05714c96db3e0007ae359a",
"name": "Amount"
},
{
"_id": "5f05714c96db3e0007ae359b",
"name": "credit"
},
{
"_id": "5f05714c96db3e0007ae359c",
"name": "total"
}
],
"_id": "5f05714c96db3e0007ae3596",
"id": 1,
"dataset": "Daily Food Report"
}
],
"__v": 0
}
]
API OUTPUT:
[
{
"_id": "5f05714c96db3e0007ae3595",
"Dataset": [
{
"parameter": [
{
"_id": "5f05714c96db3e0007ae3597",
"name": "StoreName"
},
{
"_id": "5f05714c96db3e0007ae3598",
"name": "Dates"
},
{
"_id": "5f05714c96db3e0007ae3599",
"name": "TransDesc"
},
{
"_id": "5f05714c96db3e0007ae359a",
"name": "Amount"
},
{
"_id": "5f05714c96db3e0007ae359b",
"name": "credit"
},
{
"_id": "5f05714c96db3e0007ae359c",
"name": "total"
}
],
"_id": "5f05714c96db3e0007ae3596",
"id": 1,
"dataset": "Daily Food Report"
}
],
"__v": 0
}
]

Get data from nested arrays two layers deep based on sub-index

I have this json schema
"header": {
"self": {},
"items": [
{
"_id": "5ec7e61979ec9914ecefc539",
"title": "Test",
"root": "true",
"alignment": "left",
"page": "test",
"translate": "",
"toggle": "",
"icon": "",
"IsActive": 1,
"submenu": [
{
"_id": "5ece913a353a71309084768d",
"title": "Sub Test",
"bullet": "dot",
"page": "test",
"translate": "MENU.TEST1",
"icon": "flaticon-stes-3",
"IsActive": 1
},
{
"_id": "5ece935d79972f0390997179",
"title": "Sub Test",
"bullet": "dot",
"page": "test",
"translate": "MENU.TEST2",
"icon": "flaticon-stes-3",
"IsActive": 1
}
]
}
]
}
// Index based on a previous query
this.db.collection('AssetData').find({"header.items.$.submenu.[0]._id":ObjectID("5ece913a353a71309084768d"));
//Tried with elemMatch
this.db.collection('AssetData').find(
{
"header.items": {
$elemMatch:{
"submenu": {
$elemMatch:{
"_id":ObjectID("5ece913a353a71309084768d")
}
}
}
}
});
And I am wanting to retrieve one of the sub-menu object data based on the _id from the sub-menu, but I'm having trouble retrieving it.
I'm not sure If I could use an index of the second array from another query to obtain the data, or if there's another way that I'm missing like elem match.
I am using MongoDB 3.5.6.
What would be the best way to retrieve this?
// Index based on a previous query
this.db.collection('AssetData').find({"header.items.$.submenu.[0]._id":ObjectID("5ece913a353a71309084768d")});
//Tried with elemMatch
this.db.collection('AssetData').find(
{
"header.items": {
$elemMatch:{
"submenu": {
$elemMatch:{
"_id":ObjectID("5ece913a353a71309084768d")
}
}
}
}
}).exec(function(err, item) {
console.log(item);
// here you can retrieve the stock from item, as you wish
});
hopefully it will help you

fetch array based length - mongoose

I have visitors array. Based on length I want to fetch first 40(highest visted) videos. Is there any query in mongoose for this?
"videos": [],
"description": "Runs for indai",
"status": 1,
"_id": "5e68ee512d3fe53a4426fea5",
"likes": [],
"visited": [{
"_id": "5e690d28797f5b05e066104d",
"user": "::1"
},
{
"_id": "5e690d14797f5b05e066104c",
"user": "::1"
},
{
"_id": "5e690cf7797f5b05e066104b",
"user": "::1"
}],
"comments": [],
"embed": "https://wwdalkfa.com/idaa/46221",
"category": "Mathrubhumi",
"title": "Bdis idnc - Aria.",
"link": "https://www.mdaoa.com/video/46221/dafa",
"image": "https://www.mdaoa.com/media/videos/dstmb1/46221/1b.jpg",
"keywords": "adjal","DAfa",
"__v": 0
controller
exports.getTrendingVideos = async (req, res) => {
try {
const videos = await Video.find().limit(40);
res.send(videos);
} catch (error) {}
};
First, get the length of the array and then sort it, You can do it like this
const videos = await Video.aggregate([
{ $project: { visitedCount: { $size: '$visited' } } },
{ $sort: { $visitedCount: -1 } },
]).limit(40);

Resources