I have this code
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/clboTest';
// this could have comed from a form from the browser
var objToInsert = {
_id: 2,
price: 20000,
name: stdin,
description: "20 carat gold ring. ",
//schoolID: { name: 'RUC', address: 'Roskilde', country: 'Denmark' }
};
MongoClient.connect(url, function (err, db) {
var collection = db.collection('products');
collection.insert(objToInsert, function (err, result) {
console.log(result);
db.close();
});
});
I don't want to have the information hardcoded (such as price, name). How can I input something new in the console instead of having to hardcore my insert.js file with new information over and over again?
You could use a package called readline-sync. Then you could wait for the user input before you insert the object:
var readlineSync = require('readline-sync');
var name = readlineSync.question('name: ');
var price = readlineSync.questionInt('price: ');
console.log(name);
console.log(price);
var objToInsert = {
_id: 2,
price: price,
name: name,
description: "20 carat gold ring. ",
//schoolID: { name: 'RUC', address: 'Roskilde', country: 'Denmark' }
};
Good luck!
Related
I'm making a website that checks the European VAT numbers, using the SOAP request on the official website of European Commission
I just created a script on VSCode that works perfectly inside the Terminal with Node.js
Using the "soap" node package.
The moment i try it in the browser it obviously doesn't work.
I tryed using other packages like "node-soap" and "jquery.soap" (i saw somewhere that this package should work, but i think it was years ago) with no success.
Is there a way to be able to make it work without the need for a server-side?
const soap = require('soap');
const url = 'https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
const args = [
{
countryCode: 'SE',
vatNumber: '556243997501'
},
{
countryCode: 'IE',
vatNumber: '6388047V'
}
]
;
let results = [];
let index = 0;
args.forEach((arg) => {
soap.createClient(url, (err, client) => {
if (err) throw err;
client.checkVat(arg, (err, result) => {
if (err) throw err;
let obj = {
countryCode: arg.countryCode,
vatNumber: arg.vatNumber,
requestDate: result.requestDate,
valid: result.valid,
name: result.name,
address: result.address
}
results.push(obj);
console.log(results);
});
});
index++;
});
You use wrong URL, so if you switch it will works.
From
'https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl'
To
'https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl'
Test Result
$ node get-vat.js
[
{
countryCode: 'IE',
vatNumber: '6388047V',
requestDate: Invalid Date,
valid: true,
name: 'GOOGLE IRELAND LIMITED',
address: '3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4'
}
]
[
{
countryCode: 'IE',
vatNumber: '6388047V',
requestDate: Invalid Date,
valid: true,
name: 'GOOGLE IRELAND LIMITED',
address: '3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4'
},
{
countryCode: 'SE',
vatNumber: '556243997501',
requestDate: Invalid Date,
valid: true,
name: 'IKEA Components AB',
address: 'BOX 600,SÖDRA RINGVÄGEN 4 \n343 24 ÄLMHULT'
}
]
Update
Demo code
#1 save as get-vat.js
const soap = require('soap');
const url = 'https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl';
const args = [
{
countryCode: 'SE',
vatNumber: '556243997501'
},
{
countryCode: 'IE',
vatNumber: '6388047V'
}
];
let results = [];
let index = 0;
args.forEach((arg) => {
soap.createClient(url, (err, client) => {
if (err) throw err;
client.checkVat(arg, (err, result) => {
if (err) throw err;
let obj = {
countryCode: arg.countryCode,
vatNumber: arg.vatNumber,
requestDate: result.requestDate,
valid: result.valid,
name: result.name,
address: result.address
}
results.push(obj);
console.log(results);
});
});
index++;
});
#2 install soap and run it
npm install soap
node get-vat.js
There will be multiple excel files which has the same fields but they might be aligned differently. Such as in first excel file the "price" column might be at the first sequence but at the 2nd file it might be in the 3rd sequence.
So if I were to ask to user to enter sequences under the name of fields (so I'll know the order of fields), could I only convert those fields in the order that I want to JSON with Javascript or Nodejs?
If so, how?
Example:
This is client no. 1's data: stored in this orientation
https://imgur.com/yIgOF8w
This is client no. 2's data: stored in this orientation. 1 extra data that I won't use and different than the first one.
https://imgur.com/lY96c7J
And I want to parse it exactly as how client no. 1 stored. But there are so many varieties that I'll get. So as I explained above, if I were to get the column numbers of certain fields could I get it in the exact format with first client and transform to JSON like that.
You can use the module excel js for this purpose, it has a lot of nice features.
I've updated to allow passing the column order to the readValues function.
For example:
var excel = require('exceljs');
var wb = new excel.Workbook();
var path = require('path');
var client1Path = path.resolve(__dirname, 'client1_data.xlsx');
var client2Path = path.resolve(__dirname, 'client2_data.xlsx');
function readValues(filePath, columnNumbers) {
let columnNames = Object.entries(columnNumbers).reduce((a, [key,value]) => {
a[value] = key;
return a;
}, []);
return wb.xlsx.readFile(filePath).then( () => {
var worksheet = wb.getWorksheet("Sheet1");
var values = [];
worksheet.eachRow((row) => {
let obj = row.values.reduce((o, v, index) => {
if (columnNames[index]) o[columnNames[index]] = v;
return o;
}, {});
values.push(obj);
});
return values;
});
}
async function testReadData() {
try {
let client1Data = await readValues(client1Path, { price: 1, name: 2, country: 3});
console.log('testReadData: Client 1 data: ', client1Data);
let client2Data = await readValues(client2Path, { price: 2, name: 1, country: 4});
console.log('testReadData: Client 2 data: ', client2Data);
} catch (error) {
console.error('testReadData: Error occurred: ', error);
}
}
testReadData();
I'm using the same data as in your examples (now corrected).
e.g.
Client 1 data:
$50 Jack USA
$30 Harold USA
Client 2 data:
Jack $50 Florida USA
Harold $30 California USA
The output will be like:
testReadData: Client 1 data:
[ { price: '$50', name: 'Jack', country: 'USA' },
{ price: '$30', name: 'Harold', country: 'USA' } ]
testReadData: Client 2 data:
[ { name: 'Jack', price: '$50', country: 'USA' },
{ name: 'Harold', price: '$30', country: 'USA' } ]
I have a followSchema:
var followSchema = mongoose.Schema({
user : { type: Number, ref: 'User'},
following : { type: Number, ref: 'User'}
});
I have two users.
Of the first one I need to have a list of all the users he follows.
The second one I need to check if he already follows some of the users that I gathered from the first one.
How can I do this in an affective way in Mongoose.
To get a list of followers from the first user isn't that hard, but to check if the second user follows one of them is a little harder and I have no idea how I can manage that.
This is fairly simple, all you need to do is query for the two conditions. Assuming "Follow" as the model:
Follow.find({
"user": 1,
"following": 2
})
Depending on your "scale" though, the following schema might be more useful:
var userSchema = new Schema({
"_id": Number,
"name": String,
"following": [{ "type": Number, "ref": "User" }],
"followedBy": [{ "type": Number, "ref": "User" }]
})
The query is almost identical:
User.find({
"_id": 1,
"following": 2
})
But of course it always gives you other options, as long as the general constraints for best practice with "arrays" can be adhered to.
One approach you can take is to modifying your followSchema to have the following field as an array and use the concept of population:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var userSchema = Schema({
_id: Number,
name: String,
age: Number,
followers: [{ type: Schema.Types.ObjectId, ref: 'Follow' }]
});
var followSchema = Schema({
_user: { type: Number, ref: 'User' },
following: [{ type: Number, ref: 'User' }]
});
var Follow = mongoose.model('Follow', followSchema);
var User = mongoose.model('User', userSchema);
which you can then query with the some sample users. As an example guide (untested):
var user1_id = 1,
user2_id = 2,
user3_id = 3,
user1_following = [],
user2_following = [];
var user1 = new User({ _id: user1_id, name: 'User1', age: 31 });
var user2 = new User({ _id: user2_id, name: 'User2', age: 32 });
var user3 = new User({ _id: user3_id, name: 'User3', age: 32 });
user3.save(function (err) {
if (err) return handleError(err);
})
user1.save(function (err) {
if (err) return handleError(err);
var follower3 = new Follow({ _user: user3_id });
follower3.save(function (err) {
if (err) return handleError(err);
// thats it!
});
})
user2.save(function (err) {
if (err) return handleError(err);
var follower3 = new Follow({ _user: user3_id });
follower3.save(function (err) {
if (err) return handleError(err);
// thats it!
});
})
Follow
.find({ _user: user1_id })
.exec(function (err, following) {
if (err) return handleError(err);
user1_following = following;
})
Follow
.find({ _user: user2_id })
.exec(function (err, following) {
if (err) return handleError(err);
user2_following = following;
})
You can then use Underscore's intersection() which will give you a list of values present in both arrays.
var commonFollowings = _.intersection(user1_following, user2_following);
// In the example above, commonFollowings => [3]
I'd like to aggregate results in a mongodb query, however I am not able to accomplish that in the case modeled like the following example from mongodb.org:
{
_id: "oreilly",
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English",
publisher_id: "oreilly"
}
{
_id: 234567890,
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English",
publisher_id: "oreilly"
}
My result should have this structure:
{
publishers: [
{
_id: "oreilly",
name: "O'Reilly Media",
founded: 1980,
location: "CA"
books: [
{
_id: 123456789,
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English"
},
{
_id: 234567890,
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English",
publisher_id: "oreilly"
}
]
}
]
}
But I cannot manage to use the $aggregate query on the books table to populate the publisher reference, and I don't even know if it is possible.
What are the proper strategies to get this kind of result?
One way to get the result is to simulate the join by iterate each publisher to find his books and then construct your result :)
sample in mongo shell:
var publishers = [];
var struct = {};
struct.publishers = publishers
db.publisher.find().forEach( function(publisher) {
publisher.books = db.books.find({publisher_id: publisher._id}).toArray()
publishers.push(publisher)
})
printjson(struct)
sample for drivers:
You can use db.eval to run a query as Server-side Javascript.
db.eval:
connection.db.eval(function construct(publisher){return struct}), arg ,function (e, result) {result});
db.eval function:
db.eval(function construct(publisher) {
var publishers = [];
var struct = {};
var query = publisher ? {_id:publisher} : {}
struct.publishers = publishers
db.publisher.find(query).forEach( function(publisher) {
publisher.books = db.books.find({publisher_id: publisher._id}).toArray()
publishers.push(publisher)
})
return struct
}
,null // argument to pass into function for filter, e.g. 'oreilly'
,{nolock:true})
sample with mongoose: (on collection name book)
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/book');
mongoose.connection.on('connected', function() {
mongoose.connection.db.eval(function construct(publisher) {
var publishers = [];
var struct = {};
var query = publisher ? {_id:publisher} : {}
struct.publishers = publishers
db.publisher.find(query).forEach( function(publisher) {
publisher.books = db.books.find({publisher_id: publisher._id}).toArray()
publishers.push(publisher)
})
return struct
}
,'oreilly'
,{nolock:true}, function(e,result) {
if(e) console.log(e);
console.log(JSON.stringify(result));
})
})
For example:
const customerData = [
{ id: 444, name: "Bill", age: 35, email: "bill#company.com" },
{ id: 5555, name: "Donna", age: 32, email: "donna#home.org" },
{ id: 666, name: "Cat", age: 2, email: "cat#home.org" },
{ id: 888, name: "Gandalf", age: 21000, email: "gandalf#home.org" }
];
function getDataByRange(db, table, index, lower, upper, fun){
var data = [];
var tx = db.transaction(table, "readonly");
var store = tx.objectStore(table);
var index = store.index(index);
var boundKeyRange = IDBKeyRange.bound(lower, upper, false, false);
var request = index.openCursor(boundKeyRange);
request.onsuccess = function() {
var cursor = request.result;
if (cursor) {
data.push(cursor.value);
cursor.continue();
} else {
fun(data);
}
};
}
How to get next results: Gandalf, Bill, Donna, Cat?
Now I get something like: Cat,Donna, Bill, Gandalf.
Thanks for any suggestions!
The openCursor method accepts two arguments. The second argument is optional and specifies the direction of the cursor. Because it is optional, you rarely see the second argument specified in example code, so maybe that is why it is confusing.
There are four possible direction values: next, prev, nextUnique, and prevUnique. You specify the argument as a string. next is the implied default argument.
So, use openCursor(boundKeyRange, 'prev') to iterate in reverse.