auto-increment using loopback.js and MongoDB - mongodb

i want to increase mongodb document number automatically using loopback.
I made function in mongo
function getNextSequence(name) {
var ret = db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
db.tweet.insert(
{
"_id" : getNextSequence("userid"),
"content": "test",
"date": "1",
"ownerUsername": "1",
"ownerId": "1"
}
)
It is working in mongo shell.
However when I insert using loopback.js browser (http://localhost:3000/explorer/), It is not working.
400 error(SytaxError) code is showing.
I can not use mongo function in loopback rest API ?
I think problem is quotes in this line getNextSequence("userid"),

Create a collection counters with properties value and collection
{
"name": "counters",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"type": "number",
"collection": "string"
},
"validations": [],
"relations": {},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": []
}
Now supposing your auto-increment collection name tweets.
Insert this value to counters.
{
"value" : 0,
"collection" : "tweet"
}
Now common/models/tweet.js
tweet.observe('before save', function (ctx, next) {
var app = ctx.Model.app;
//Apply this hooks for save operation only..
if(ctx.isNewInstance){
//suppose my datasource name is mongodb
var mongoDb = app.dataSources.mongodb;
var mongoConnector = app.dataSources.mongodb.connector;
mongoConnector.collection("counters").findAndModify({collection: 'tweet'}, [['_id','asc']], {$inc: { value: 1 }}, {new: true}, function(err, sequence) {
if(err) {
throw err;
} else {
// Do what I need to do with new incremented value sequence.value
//Save the tweet id with autoincrement..
ctx.instance.id = sequence.value.value;
next();
} //else
});
} //ctx.isNewInstance
else{
next();
}
}); //Observe before save..

I would love to add 1 more point to Robins Answer,you can add upsert:true so that it automatically creates the document if it doesn't exist
tweet.observe('before save', function (ctx, next) {
var app = ctx.Model.app;
//Apply this hooks for save operation only..
if(ctx.isNewInstance){
//suppose my datasource name is mongodb
var mongoDb = app.dataSources.mongodb;
var mongoConnector = app.dataSources.mongodb.connector;
mongoConnector.collection("counters").findAndModify({collection: 'tweet'}, [['_id','asc']], {$inc: { value: 1 }}, {new: true,upsert:true}, function(err, sequence) {
if(err) {
throw err;
} else {
// Do what I need to do with new incremented value sequence.value
//Save the tweet id with autoincrement..
ctx.instance.id = sequence.value.value;
next();
} //else
});
} //ctx.isNewInstance
else{
next();
}
}); //Observe before save..

You can do something like in this example for loopback 4
let last_record = await this.testRepository.findOne({order: ['id DESC']});
if(last_record) invoice.id = last_record.id+1;
This will generate your model with the property:
#property({
type: 'number',
id: true,
default: 1,
generated: false
})
id: number;
Hopefully, this helps, please write me if there is any other code. Thanks

If you want to use MongoDB operators directly in loopback methods you need to enable the option "allowExtendedOperators", you can do so on a per model basis or at the data source level (will apply to all models using the data source).
datasources.json:
"MongoDs": {
"host": "127.0.0.1",
"port": 27017,
"url": "mongodb://localUser:MYPASSWORD!#127.0.0.1:27017/test-database",
"database": "test-database",
"password": "MYPASSWORD!",
"name": "MongoDs",
"user": "localUser",
"useNewUrlParser": true,
"connector": "mongodb",
"allowExtendedOperators": true
},

Related

How to create in mongoose, if it exists, update it in mongoose

I have problem when I want create new model or if not exist, update it.
For example, I have data in a database:
{
"unix": 1668380400,
"type": "soup",
"order": 1,
"value": "Chicken"
},
{
"unix": 1668380400,
"type": "main",
"order": 0,
"value": "Gulash"
},
{
"unix": 1668553200,
"type": "soup",
"order": 0,
"value": "Asian"
}
}
I want to get to the point that when unix and type and order are the same - modify the value. But if the element with the same unix, order and type is not found in the database - add a completely new record to the db.
I thought this was how I would achieve the desired state. But a mistake.
router.post("/add", async (req, res) => {
const data = req.body;
await data.map((el) => {
const { unix, type, order, value } = el;
Menu.findOneAndUpdate(
{ unix, type, order },
{ unix, type, order, value },
{ new: true, upsert: true }
);
});
res.status(201).json({ status: true });
});
req.body:
[
{
"unix": 1668380400,
"type": "main",
"order": 2,
"value": "Sushi"
},
{
"unix": 1668553200,
"type": "soup",
"order": 0,
"value": "Thai"
}
]
Thanks for any help.
I think I found a solution. Everything works as it should, but wouldn't it be better to send the data with JSON.stringify() and then parse this data on the servers using JSON.parse()?
Another thing is the map method. Is it OK like this? Can't cause throttling?
router.post("/add", (req, res) => {
const data = req.body;
data.map(async (el) => {
const { unix, type, order, value } = el;
await Menu.findOneAndUpdate(
{ unix, type, order },
{ value },
{ upsert: true }
);
});
res.status(201).json({ status: true });
});

mongoDB autcomplete returns empty array

I am using mongodb's sample movie database (https://docs.atlas.mongodb.com/sample-data/sample-mflix#std-label-sample-mflix) to experiment with mongodb's autocomplete functionality. The search always returns an empty array. I have set up a Search Index as follows:
{
"mappings": {
"dynamic": false,
"fields": {
"title": [
{
"minGrams": 3,
"tokenization": "edgeGram",
"type": "autocomplete"
}
]
}
}
}
The model and the search query are setup as follows:
// Creating the Movies model
const Movies = mongoose.model("Movies", new mongoose.Schema({}), "movies");
// Impplementing autocomplete search
app.get("/search", async (req, res) => {
try {
let result = await Movies.aggregate([
{
$search: {
autocomplete: {
path: "title",
query: req.query.title,
fuzzy: {
maxEdits: 2,
prefixLength: 3,
},
},
},
},
]);
res.status(200).json({
status: "success",
results: result.length,
data: { result },
});
} catch (error) {
console.log(error);
}
});
I am using postman to run test queries and a sample query is: 127.0.0.1:3030/search?title=black
The model can be queried using .find(), for example, and returns the full collection of documents.
Any and all help is greatly appreciated.

"Cannot read property 'apply' of undefined"? in loopback 3

i don't know why i have this error
when i executing the method in the loopback explorer gives the error
This is the .js file used in the project
'use strict';
module.exports = function(Puntoventa) {
var app = require('../../server/server');
Puntoventa.getAll = function() {
Puntoventa.find({ where: { nombre: !null } }, function(err, punto) {
if (err) return callback(err);
return punto;
});
}
}
and this is the model .json
"name": "puntoVenta",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"acls": [],
"methods": {
"getAll": {
"accepts": [],
"returns": [{
"arg": "punto",
"type": "object",
"root": true,
}],
"http": [{
"path": "/getAll",
"verb": "get"
}]
}
}
The error is due to a bug in sql query, you cannot use !null instead you can use neq given by loopback
Puntoventa.find({ where: { nombre: { "neq": null} } }, function(err, punto) {
if (err) return callback(err);
return punto;
});
Please use { "neq": null} } and define callback in getAll().
Puntoventa.getAll = function(callback) {
Puntoventa.find({ where: { nombre: { "neq": null} } } }, function(err, punto) {
if (err) return callback(err);
return callback(null,punto);
});
}

Mongoose: Update nested document

I have following JSON structure,
{
"projectId": "service-request-service",
"projectVersion": [{
"version":"1",
"localConfig": [{
"port": "3003",
"mongoURI": "mongodb://localhost:27017/serviceRequest",
"MQ": "RMQ",
"logLevel": "2",
"version": "1.1",
"created": "03-06-2018 03:11:00 PM",
"active": "N"
},
{
"port": "3004",
"mongoURI": "mongodb://localhost:27017/serviceRequest",
"MQ": "IMQ",
"logLevel": "1",
"version": "1.2",
"created": "07-06-2018 03:11:00 PM",
"active": "Y"
}]
}]
}
Now, I want to update all port and active values of localConfig. I tried using different ways,
using markModified
ProjectConfig.findOne({'projectId' : projectId,
'projectVersion.version' : version})
.exec(function(err,pc){
pc.projectVersion[0].localConfig[0].active = "N";
pc.projectVersion[0].localConfig[0].port = "5555";
pc.markModified('localConfig');
pc.save(function(err,result){
if (err) {
console.log(err);
}
console.log("## SUCCESSFULLY SAVED ");
});
});
Iterating using for loop.
ProjectConfig.findOne({'projectId' : projectId,
'projectVersion.version' : version}).exec(function(err,pc){
for(i = 0; i < pc.projectVersion.length ; i++){
for(j = 0; j < pc.projectVersion[i][envQuery].length ; j++){
pc.projectVersion[i][envQuery][j].active = 'N';
pc.projectVersion[i][envQuery][j].port = '5555';
}
}
pc.save(function (err, result) {
if (err) {
console.log(err);
}
console.log("## SUCCESSFULLY SAVED ");
});
});
Using arrayFilters,
let conditions = {};
let update = {$set: {"projectVersion.$[i].localConfig.$[].port": "5555"}};
let options = {arrayFilters:[{"i.version":"1"}]};
pc.update(conditions,update,options,function(err,result){
if (err) {
console.log(err);
}
console.log("## SUCCESSFULLY SAVED ");
});
But, I am getting below error.
MongooseError: Callback must be a function, got [object Object]
Please provide me the way to update document.
Current version of MongoDB : v3.6.6 & Mongoose : ^5.0.14
Using arrayFilters, I am not applying update method on scheme rather applying on object return by find method.
When I directly apply update method on schema, its working.
let conditions = { "projectId" : "32804-service-request-service" };
let update = { $set: {
"projectVersion.$[i].localConfig.$[j].port" : "5555",
}
};
let options = {arrayFilters:[{"i.version":"1" },{ "j.port" : "3003"}]};
ProjectConfig.update(conditions, update, options, function(err,result){
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'SUCCESS',
obj: result
});
});

how to write findOneAndUpdate query in express.js?

i have shown my data , which is stored in database like this
{
"_id": {
"$oid": "5799995943d643600fabd6b7"
},
"Username": "xx",
"Email": "xx#gmail.com",
"Info": "Deactivate",
"Description": "aajdjdjddjdkjddjdjdhdj",
"VerificationCode": "594565",
"VerificationExpires": {
"$date": "2016-10-07T10:20:20.077Z"
}
}
My controller:
if Username, Email, Info are matched I need to update " Info = 'Active' " this is working at the same time i need to delete 'VerificationCode' field and 'VerificationExpires' field how can i achieve this?
exports.updatearticle = function(req, res) {
Article.findOneAndUpdate(
{ "Username":'xx', "Email":'xx#gmail.com', "Info": "Deactivate" },
{ "$set": { "Info": "Active" } },
{ "new": true }
function (err, doc) {
if (err) { // err: any errors that occurred
console.log(err);
} else { // doc: the document before updates are applied if `new: false`
console.log(doc); // , the document returned after updates if `new true`
console.log(doc.Info);
}
}
);
};
above condtion matched and info getting changed but i want to delete VerificationCode,VerificationExpires some one help me out
exports.updatearticle = function(req, res) {
Article.findOne( { "Username":'xx', "Email":'xx#gmail.com', "Info": "Deactivate" }, function(err, result){
if (!err && result) {
result.Info = "Active"; // update ur values goes here
result.VerificationCode = "";
result.VerificationExpires = {};
var article = new Article(result);
article.save(function(err, result2){
if(!err) {
res.send(result2);
} else res.send(err);
})
} else res.send(err);
});
}
home this may help