mongo query from loopback issue - javascript

I am trying to query in mongo db from loopback model. But i am not getting any result from monogdb
This is how my document looks like in mongodb
{"_id":"5b9f8bc51fbd7f248cabe742",
"agentType":"Online-Shopping",
"projectId":"modroid-server",
"labels":["category","price"],
"phrases":["Look for _^ct_ in _^p_ ",
"I need _^ct_ in _^p_",
"can you search for _^ct_ in _^p_"]
}
here is my datasource file
{
"db": {
"name": "db",
"connector": "memory"
},
"modroid-server": {
"host": "localhost",
"port": 27017,
"url": "",
"database": "modroid-server",
"password": "",
"name": "modroid-server",
"user": "",
"connector": "mongodb"
}
}
and here is model-config file
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false,
"options": {
"strictObjectIDCoercion": true
}
},
"Role": {
"dataSource": "db",
"public": false
},
"agent": {
"dataSource": "modroid-server", // here is my mongodb
"public": true
}
}
and here is my code to query in mongodb
module.exports = function (Agent) {
Agent.getDataSource().connector.connect(function (err, db) {
var collection = db.collection("text-responses");
collection.find({ "where": { "labels": ["category", "price"] } }, function (err, res) { // define whichever query you need
console.log("collection find res:"+res);
console.log("collection find err:"+err);
if(err) {
cb(err);
return;
}
res.toArray(function (err, realRes) { // this part is crucial
// otherwise if you try to print res you will get a dump of the db object
if(err) {
cb(err);
return;
}
console.log("documnet result:"+realRes);
console.log("document err:"+err);
})
})
}
);
}
and when i hit that rest api. I get this output
collection find res:[object Object]
collection find err:null
documnet result:
document err:null
please help me where i am doing thing wrong. I am stuck in that from couples of days.
Edited
when i just print res it gives me huge data which starts as
Cursor {
pool: null,
server: null,
disconnectHandler:
Store {
s: { storedOps: [], storeOptions: [Object], topology: [Object] },
length: [Getter] },
bson: BSON {},
ns: 'modroid-server.text-responses',
cmd:
{ find: 'modroid-server.text-responses',
limit: 0,
skip: 0,
query: { where: [Object] },
slaveOk: true,
readPreference: ReadPreference { mode: 'primary', tags: undefined } },

Look like text-responses is Not a model.
Try with Direct Model Agent.
module.exports = function (Model) {
Model.getDataSource().connector.connect(function (err, db) {
Model.find({ "where": { "labels": ["category", "price"] } }, function (err, res) { // define whichever query you need
console.log("collection find res:"+res);
console.log("collection find err:"+err);
})
});
}
Or
By collection
module.exports = function (Model) {
Model.getDataSource().connector.connect(function (err, db) {
var collection = db.collection("collection-name"); //use agent
collection.find({ "where": { "labels": ["category", "price"] } }, function (err, res) { // define whichever query you need
console.log("collection find res:"+res);
console.log("collection find err:"+err);
})
}
);
}

Related

$unset not working in node (Mongoose) while working in mongosh

how come wouldn't Mongoose and Mongosh return the same answer?
In the Schema, I have user ID and IoT device (smart light). Goal that I am trying to achieve is to remove completely first item in "smart_light" section.
Using Mongosh code works fine, but Mongoose is not removing the item. No errors are thrown, just "{acknowledged: false}". Mongoose is used with Node.
Schema (I am using replica set):
{
"UserID": "6276a2a6e59469e642801f4f",
"smart_light": {
"1": {
"Device_ID": "1",
"Device_Details": {
"Online_Status": true,
"DeviceManufacturer": "Philips",
"Model": "S-Li-7",
"Serial_Number": "302504-519574",
"Last_Update": {
"Date": "2014-05-11 19:59:37",
"Version": "V4",
"Update_Pending": false
},
"Communication_Protocol_Set": [
"Zigbee",
"Zwave"
],
"Spare_Parts": [
"Bridge"
]
},
"Device_Status": {
"Colour": "#08b8cd"
}
},
"2": {
"Device_ID": "2",
"Device_Details": {
"Online_Status": true,
"DeviceManufacturer": "Philips",
"Model": "S-Li-5",
"Serial_Number": "136985-212439",
"Last_Update": {
"Date": "2011-08-16 03:45:29",
"Version": "V2",
"Update_Pending": true
},
"Communication_Protocol_Set": [
"Zwave"
],
"Spare_Parts": [
"Bridge"
]
},
"Device_Status": {
"Colour": "#4bf14b"
}
}
}
}
Mongosh:
db.iot_customer_devices.updateOne(
{UserID: "6276a2a6e59469e642801f4f"},
{"$unset":{"smart_light.1":""}});
Mongoose:
IoT_Customer_Device.updateOne(
{UserID: "6276a2a6e59469e642801f4f"},
{$unset: {"smart_light.1":""}},
{ safe: true, multi:true },
function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}}
);
===================================================================
Update1:
It seems that if I try to remove (with mongoose) "UserID", this works... But objects cannot be removed so far?
IoT_Customer_Device.findOneAndUpdate(
{ UserID: "6276a2a6e59469e642801f18" },
{$unset: {"UserID":1}}, (err, res) => {
console.log(res);
});
This is now closed, answer has been found:
IoT_Customer_Device.updateOne(
{ UserID: "6276a2a7e59469e642801f86" },
[
{ $unset: "smart_light.1" }
],
(err, data) => {
if (!err) {
res.redirect('/devices/smart_light');
}
else { console.log('Error in device delete :' + err); }
}
);
This is working as intended, found my inspiration here

Loopback:TypeError: Cannot read property 'find' of undefined

I saw a few questions like mine but couldn't find any solutions that worked so I thought I'd ask.
I'm trying to pull all my data from my database so I can select parts of it in my app. I had my database working fine but when I tried to pull the pictures it failed and keeps giving me this error and also does not seem to receive the data from the database:
app.model.users.find((err,result)=>{
^
TypeError: Cannot read property 'find' of undefined
Here is my code:-
server.js:-
'use strict';
const loopback = require('loopback');
const boot = require('loopback-boot');
const app = module.exports = loopback();
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
const baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
const explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
app.start();
});
console.log(Object.keys(app.models));
app.model.users.find((err,result)=>{
if(result.length ===0){
const user={
email:'jhanvi#gmail.com',
password:'jhanvi',
username: 'jhanvi',
};
app.models.user.create(user,(err,result)=>{
console.log("tried to create user ",err,result);
});
}
});
app.models.user.afterRemote('create', (ctx,user,next) =>{
console.log("new user is",user);
app.models.Profile.create({
first_name: user.username,
created_at: new Date(),
userId: user.id
},(err,result)=>{
if(!err && result){
console.log("created new profile",result);
}
else{
console.log("there is an error ",err);
}
});
next();
});
user.json:-
{
"name": "user",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"email": {
"type": "string"
},
"password": {
"type": "string"
}
},
"validations": [],
"relations": {
"Profile": {
"type": "hasMany",
"model": "Profile",
"foreignKey": ""
},
"accessTokens":{
"type":"hasMany",
"model":"CustomAccessToken",
"foreignKey":"userId"
}
},
"acls": [],
"methods": {}
}
Profile.json :-
{
"name": "Profile",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"created_at": {
"type": "date"
},
"age": {
"type": "number"
},
"history": {
"type": [
"object"
]
}
},
"validations": [],
"relations": {
"user": {
"type": "belongsTo",
"model": "user",
"foreignKey": "userId"
}
},
"acls": [],
"methods": {}
}
In your model you refer to user.
app.model.users.find((err,result)
should then surely be
app.model.user.find((err,result)
(i see you seem to be using both versions...)

How to make a get request to retrieve the latest document of an index in the elasticsearch cluster?

I am developing a node.js application to get the latest value of an index from an elastic cluster. My logstash server pipes data to elasticsearch every second. So, the elasticsearch index gets updated every second. Every second a new document is added to the elasticsearch index.
Here is a sample JSON document
{
"_index": "weather",
"_type": "doc",
"_id": "eMIs_mQBol0Vk4cfUzG5",
"_version": 1,
"_score": null,
"_source": {
"weather": {
"main": "Clouds",
"icon": "04n",
"description": "broken clouds",
"id": 803
},
"#version": "1",
"clouds": {
"all": 75
},
"main": {
"humidity": 36,
"pressure": 1022,
"temp": 41,
"temp_max": 26,
"temp_min": 26
},
"wind": {
"deg": 360,
"speed": 3.6
},
"visibility": 16093,
"#timestamp": "2018-08-03T05:04:35.134Z",
"name": "Santa Clara"
},
"fields": {
"#timestamp": [
"2018-08-03T05:04:35.134Z"
]
},
"sort": [
1533272675134
]
}
Here is the picture of the table,
My node.js code looks like this,
let express = require('express');
let app = express();
let elasticsearch = require('elasticsearch');
app.get('/', function(req, res) {
res.send('Hello World!');
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
let client = new elasticsearch.Client({
host: ['http://localhost:9200']
});
client.ping({
requestTimeout: 30000,
}, function(error) {
if (error) {
console.error('elasticsearch cluster is down!');
} else {
console.log('Everything is ok');
}
});
async function getResponse() {
const response = await client.get({
index: 'weather',
type: 'doc',
id: 'KsHW_GQBol0Vk4cfl2WY'
});
console.log(response);
}
getResponse();
I am able to retrieve the JSON document based on the id of the index. But, I want to retrieve the latest JSON document. How can I configure my server to read the latest document every second from the server? Is there a way to retrieve the latest JSON document(without knowing the id in advance)?
Can someone please help me with this? I would really appreciate if you could help.
Thanks in advance!
If you have a timestamp field in your index and that is updated/added after every document is indexed. Then you can simply perform a sort on timestamp field with size=1.
The below query will give you the most recent value:
{
"query": {
"match_all": {}
},
"size": 1,
"sort": [
{
"timestamp": {
"order": "desc"
}
}
]
}
Not sure of the syntax of node.js but something like this would work:
client.search({
index: 'weather',
type: 'doc'
body: {
sort: [{ "timestamp": { "order": "desc" } }],
size: 1,
query: { match_all: {}}
}
});
Based on your mapping you've #timestamp so you should use:
client.search({
index: 'weather',
type: 'doc'
body: {
sort: [{ "#timestamp": { "order": "desc" } }],
size: 1,
query: { match_all: {}}
}
});

Overwrite default error messages of loopback

I'm trying to overwrite the default error messages from loopback. That's how i'm doing:
server/middleware.json:
{
"initial:before": {
"loopback#favicon": {}
},
"initial": {
"compression": {},
"cors": {
"params": {
"origin": true,
"credentials": true,
"maxAge": 86400
}
},
"helmet#xssFilter": {},
"helmet#frameguard": {
"params": [
"deny"
]
},
"helmet#hsts": {
"params": {
"maxAge": 0,
"includeSubdomains": true
}
},
"helmet#hidePoweredBy": {},
"helmet#ieNoOpen": {},
"helmet#noSniff": {},
"helmet#noCache": {
"enabled": false
}
},
"session": {},
"auth": {},
"parse": {},
"routes": {
"loopback#rest": {
"paths": [
"${restApiRoot}"
]
}
},
"files": {},
"final": {
"loopback#urlNotFound": {}
},
"final:after": {
"loopback#errorHandler": {},
"errorHandler": {}
}
}
server/middleware/error-handler.js:
module.exports = (error, req, res, next) => {
console.log('a')
};
Before overwrite, i need first intercept the error message, but i'm not getting how...
Thanks!
You can access your error message and overwrite it as below
module.exports = (error, req, res, next) => {
console.log(error.message); // logs out original error message
error.message = 'Your Custom Error message'; // this will overwrite the error message
next(error); // this is important
};
Other properties of the error object are
statusCode, name, stack
& also
details, messages if applicable

Deleting item mongodb and node async

I've having trouble removing a item from the upload [] object.
The below represents a User, keys[] represents a key for which file uploads get associated with, and uploads[] are files beneath that key. These are all documents embedded within the User model. I realize now I'd have been way better off using references but I am stuck with this for now. Here is the function I'm using right now to find the uploads item,
______________THIS IS MY CURRENT FUNCTION_____________________
I'll be honest I am using async and I don't exactly understand it well. Is there a different async function or way to lookup these items in mongo that would work better?
Current issues: 1) This will continue looping through until the end even after it finds the correct items. 2) How can I delete the upload item?
exports.getApiDelete = function (req, res, next) {
User.findById(req.user.id, function(err, user) {
if (err) return next(err);
console.log("User ID found: "+ user._id);
//loop though user keys
async.forEach(user.profile.keys, function(item, callback) {
//verify key exists
if(item.key==req.params.scriptkey){console.log("KEY FOUND")};
async.forEach(item.uploads, function(item, callback) {
//verify file exits
console.log(req.params.file_id);
if(item._id == req.params.file_id){
// DELETE FUNCTION HERE?
};
}, function(err){
console.log('Error during async lookup: '+err);
});
}, function(err){
console.log('Error during async lookup: '+err);
});
});
};
______________________________THIS MY USER MODEL_____________________
{
"__v": 19,
"_id": {
"$oid": "53c812c4e75ab0b013f3c6bc"
},
"email": "fake#mailinator.com",
"password": "fake",
"profile": {
"gender": "",
"keys": [
{
"_id": {
"$oid": "53c8130ae75ab0b013f3c6bd"
},
"status": false,
"iteration": 0,
"created": {
"$date": "2014-07-17T18:16:42.568Z"
},
"uploads": [],
"description": "This is being run from my Windows Desktop.",
"location": "Front Row",
"name": "fake_Desktop",
"key": "80f94c80-0dde-11e4-ae14-43922f7b8f23"
},
{
"_id": {
"$oid": "53c814ade75ab0b013f3c6be"
},
"created": {
"$date": "2014-07-17T18:23:41.777Z"
},
"description": "Windows VM test.",
"iteration": 12,
"key": "7ad78410-0ddf-11e4-ae14-43922f7b8f23",
"location": "Back Right",
"name": "fake2_Desktop",
"status": false,
"uploads": [
{
"_id": {
"$oid": "53c81517e75ab0b013f3c6bf"
},
"ip": "10.0.1.156",
"fname": "hklm_1.txt",
"iteration": 1,
"created": {
"$date": "2014-07-17T18:25:27.241Z"
},
"filepath": "script_uploads/7ad78410-0ddf-11e4-ae14-43922f7b8f23_1_hklm_1.txt"
},
{
"_id": {
"$oid": "53c8151ae75ab0b013f3c6c0"
},
"ip": "10.0.1.156",
"fname": "hklm_1.txt",
"iteration": 2,
"created": {
"$date": "2014-07-17T18:25:30.634Z"
},
"filepath": "script_uploads/7ad78410-0ddf-11e4-ae14-43922f7b8f23_2_hklm_1.txt"
}
]
}
}
You want to remove only from array? If yes, use
for(var i =0, j = item.uploads.length; i < j; i++) {
//verify file exits
console.log(req.params.file_id);
if(item.uploads[i]._id == req.params.file_id){
item.uploads.slice(i, 1);
};
And at the end use: user.save(function(err){});
If there is anything you want to delete from file system, use:
fs = require('fs');
fs.unlink( FILE PATH , function(err) {
console.log(err);
});
Also you don't really need async version of forEach, cause User.findById is asynchronous itself and whole process goes on background.
This will continue looping through until the end even after it finds
the correct items.
There is no "break" for async.forEach. So if you don't want to do unwanted process, use for as I did and append a break point.
There is no async call inside your loops, so you don't need async.forEach(). Using javascript native loops would be just fine:
exports.getApiDelete = function (req, res, next) {
User.findById(req.user.id, function(err, user) {
if (err) return next(err);
console.log("User ID found: "+ user._id);
user.profile.keys.forEach(function(el) {
if(el.key==req.params.scriptkey){console.log("KEY FOUND");}
el.uplaods.forEach(function(item) {
console.log(req.params.file_id);
if(item._id == req.params.file_id){
// DELETE FUNCTION HERE?
}
});
});
});
};

Categories