Sequelize,findAll, attributes can not rename column - node.js

My Table data:
Mytable(id,col1,col2,time)
with data
Mytable("1","val1","val2","time")
I fetch data by this code:
async function getData() {
const mytables = await Mytable.findAll(
{ where: { id: othervalue }},
{ attributes: ['col1',['id', 'newnameid'],'newnamecol1']}
);
console.log(JSON.stringifty(mytables));
}
getData();
I want data only like this:
[ {'newnameid':'1','newnamecol1':'val1'} ]
But I got this:
[ {'id':'1','col1':'val1','col2':'val2,'time':'time''} ]
Uhm, what is possible wrong with this code ?

async function getData() {
const mytables = await Mytable.findAll(
{
where: { id: othervalue },
attributes: ['col1',['id', 'newnameid'],'newnamecol1']
},
);
console.log(JSON.stringifty(mytables));
}
getData();
Updated:
attributes: ['col1',['id', 'newnameid'],'newnamecol1'] -> inside first {}

Use findAll and
const convertedData = await rows.map(arrObj => {
return {
newname: reqbody.olddata
}})

Related

How to access the value of a constant outside a function?

I am using Node with websocket and I have this function:
const validatedCep = async () => {
const data = await axios
.get(`https://viacep.com.br/ws/${message}/json/`)
.then((res) => {
return res.data;
})
.catch((err) => {
return err.response;
});
console.log(1, data);
return data;
};
if (this.props.dataType === "CEP") {
validatedCep();
}
How can I get the value returned in response and access that value outside the validatedCep function?
I need this value to be able to check if it will return the value of the answer or an error, so that I can proceed with the logic of the function.
Full function:
import { MessageSender } from "./message-sender";
import { WappMessage } from "./wapp-message";
import axios from "axios";
export type FormProps = {
error?: string;
text: string;
dataType: string;
typingDuration: number;
};
export class WappFormMessage extends WappMessage<FormProps> {
constructor(
readonly props: FormProps,
private next: WappMessage<any> | undefined,
protected messageSender: MessageSender<FormProps>
) {
super(props, "response", true, messageSender);
}
getNext(message: string): WappMessage<any> | undefined {
const regexs = [
{ type: "email", regex: "^[a-z0-9]+#[a-z0-9]+\\.[a-z]+\\.?([a-z]+)?$" },
{ type: "CPF", regex: "^\\d{3}\\.?\\d{3}\\.?\\d{3}\\-?\\d{2}$" },
{ type: "CNPJ", regex: "^d{2}.?d{3}.?d{3}/?d{4}-?d{2}$" },
{
type: "cellPhone",
regex: "(^\\(?\\d{2}\\)?\\s?)(\\d{4,5}\\-?\\d{4}$)",
},
{ type: "phone", regex: "(^\\(?\\d{2}\\)?\\s?)(\\d{4}\\-?\\d{4}$)" },
{ type: "birthDate", regex: "(^\\d{2})\\/(\\d{2})\\/(\\d{4}$)" },
];
const dataTypes = [
"email",
"birthDate",
"CPF",
"CNPJ",
"cellPhone",
"phone",
];
const validateData = (element: string) => {
if (this.props.dataType === element) {
const getRegex = regexs.find((regexs) => regexs.type === element);
const regexCreate = new RegExp(getRegex!.regex, "i");
const validate = regexCreate.test(message);
return validate;
}
return true;
};
const isValid = dataTypes.find(validateData);
if (!isValid) {
return new WappFormMessage(
{
error: "Invalid data!",
...this.props,
},
this.next,
this.messageSender
);
}
const validatedCep = async () => {
const data = await axios
.get(`https://viacep.com.br/ws/${message}/json/`)
.then((res) => {
return res.data;
})
.catch((err) => {
return err.response;
});
console.log(1, data);
return data;
};
if (this.props.dataType === "CEP") {
validatedCep();
}
return this.next;
}
async send(remoteJid: string): Promise<void> {
await this.messageSender.send(
remoteJid,
this.props,
this.props.typingDuration
);
}
}

Is there a better way to define these funtions?

There has to be a better way of doing this.
I feel like I'm repeating myself.
Can anyone help? I'm a bit new to this. Is there some way that these different data functions and variables into a class that I can inherit from?
Thanks in advance!
import { Guild, GuildMember, TextChannel } from "discord.js"
import mafiaRoleSchema from "./models/mafiaRole-schema"
import willSchema from "./models/will-schema"
interface data<type>{
// MemberID: message
[key: string]: type
}
let willData = {} as data<string>
export async function setWillData(key : GuildMember, value: string) {
willData[key.id] = value
await willSchema.findOneAndUpdate({
_id: key.id
}, {
_id: key.id,
value
}, {
upsert: true
})
}
export async function getWillData(key : GuildMember): Promise<string | null>{
let data = willData[key.id]
if(!data){
const results = await willSchema.findById(key.id)
if (!results){
return null
}
const {text} = results
data = willData[key.id] = text
}
return data
}
let mafiaRoleData = {} as data<string>
export async function setmafiaRoleData(key : GuildMember, value: string) {
mafiaRoleData[key.id] = value
await mafiaRoleSchema.findOneAndUpdate({
_id: key.id
}, {
_id: key.id,
value
}, {
upsert: true
})
}
export async function getmafiaRoleData(key : GuildMember): Promise<string | null>{
let data = mafiaRoleData[key.id]
if(!data){
const results = await mafiaRoleSchema.findById(key.id)
if (!results){
return null
}
const {text} = results
data = mafiaRoleData[key.id] = text
}
return data
}
let welcomeData = {} as data<[TextChannel, string]>
export async function setwelcomeData(key : Guild, value: [TextChannel, string]) {
welcomeData[key.id] = value
const [target, text] = value
await mafiaRoleSchema.findOneAndUpdate({
_id: key.id
}, {
_id: key.id,
text,
channelId: target.id
}, {
upsert: true
})
}
export async function getwelcomeData(key : Guild): Promise<[TextChannel, string] | null>{
let data = welcomeData[key.id]
if(!data){
const results = await mafiaRoleSchema.findById(key.id)
if (!results){
return null
}
const {channelId, text} = results
const channel = key.channels.cache.get(channelId) as TextChannel
data = [channel, text]
}
return data
}
I've tried putting the functions into the interface. But that didn't work. I honestly don't know where to go.
I know it seems like a lot, but this isn't as bad as you think. Your welcome message code is sufficiently different than your other code, which merits it having its own functions.
As for the mafia and will data, you could do an abstraction kind of like this:
import mafiaRoleSchema from "./models/mafiaRole-schema"
import willSchema from "./models/will-schema"
interface Data<type>{
// MemberID: message
[key: string]: type
}
type Schema = typeof mafiaRoleSchema | typeof willSchema // this could be more generic if you have access to those types
class SchemaController {
private schema: Schema
private data: Data<string>
constructor(schema: Schema) {
this.schema = schema
this.data = {}
}
async setData(key: GuildMember, value: string) {
this.data[key.id] = value
await this.schema.findOneAndUpdate({
_id: key.id
}, {
_id: key.id,
value
}, {
upsert: true
})
}
async getData(key : GuildMember): Promise<string | null> {
let data = this.data[key.id]
if(!data){
const results = await this.schema.findById(key.id)
if (!results){
return null
}
const {text} = results
data = this.data[key.id] = text
}
return data
}
const mafiaController = new SchemaController(mafiaRoleSchema)
const willController = new SchemaController(willSchema)

How to do pagination with a mongodb aggregate?

While working on MongoDB.I have a problem with doing Pagination.When I'm trying to include Paginaiton with aggerate.I'm also trying to include facets in this.
My code: Just for doing search
app.get("/search", async(req, res) => {
try {
const text = req.query.text
let result = await collection.aggregate([
{
'$search': {
'text': {
'query': `${text}`,
'path': 'title'
}
}
}
]).toArray();
res.send(result)
} catch (error) {
console.error(error)
}
})
This works for both search as well as pagination.
like this, see, It doesn't require any optional request.query.page.
http://localhost:4000/search?text=mango
http://localhost:4000/search?text=mango?page=1
Now, I want to include the pagination with facets search as well...So,
server.get("/search", async(req, res) => {
try {
const key = req.query.key;
const value = req.query.value;
const text = req.query.text;
const page = req.query.page; //Page query create
let result = await collection.aggregate([
{
'$search': {
'text': {
'query': `${text}`,
'path': 'title'
}
}
},
{
'$match': {
[key]: `${value}`
}
}
]).toArray();
res.send(result)
} catch (error) {
console.error(error)
}
})
work for this: without no.of Pages
http://localhost:4000/search?text=Mango&key=Brand&value=rasna
Doesn't work for Pagination:
http://localhost:4000/search?text=Mango&key=Brand&value=rasna&page=2
where I'm wrong here? Do I need to create any additional function to make this works or Something else?
you can use both $skip and $limit aggregation pipelines to achieve this purpose. imagine that we want to have only 20 items per page. so our code looks like this:
server.get("/search", async(req, res) => {
try {
const key = req.query.key;
const value = req.query.value;
const text = req.query.text;
const page = req.query.page - 1; //We subtract one because we don't want skip first twenty items in first page
let result = await collection.aggregate([
{
'$search': {
'text': {
'query': `${text}`,
'path': 'title'
}
}
},
{
'$match': {
[key]: `${value}`
}
},
{ $skip: page * 20 },
{ $limit: 20 }
]).toArray();
res.send(result)
} catch (error) {
console.error(error)
}
})

Typeorm find options with order and where

I would like to order this find function through the table relation.
const [people, total] = await typePersonServiceInstance.find(
{
take,
skip,
where: (qb: any) => {
qb.where('person.type IN (:...type)', { type });
qb.andWhere('person.status IN (:...status)', { status });
if (query.search) {
qb.andWhere(new Brackets((subQb) => {
subQb.where('name like :name', { name: `%${query.search}%` });
subQb.orWhere('fantasyName like :fantasyName', { fantasyName: `%${query.search}%` });
subQb.orWhere('person.city like :city', { city: `%${query.search}%` });
subQb.orWhere('person.state like :state', { state: `%${query.search}%` });
subQb.orWhere('person.id = :id', { id: query.search });
}));
}
},
order: {
person: {
status: 'ASC'
}
}
},
);
The issue i'm facing is when trying to order by some attribute from person table, if I do
order: {
anyColumnFromTypePersonHere: 'ASC' | 'DESC'
}
It works pretty fine, but if I want to order by status (that is an attribute from person) it will not work
Just add this line:
qb.addOrderBy('person.status', "ASC") ;

Creating stub for sequeilze models with association

I am using mocha and chai for writing test for RESTful APIs
I have read some articles where people suggests to create stubs for queries, and you shouldn't be actually making a database query.
But How would I make sure if it works?
See below controller.
const Op = require('sequelize').Op
//Models
const {
Item,
Location,
Combo,
Service,
ComboItem,
ItemLocation
} = require('../models')
const _ = require('lodash')
//Services
const paginate = require('../services/PaginationService')
const getAllItems = async function(req, res) {
if(req.query.location_id){
let items
const item = await Location.findOne({
where: {
id: 1
},
include: {
model: Item,
through: {
model: ItemLocation,
attributes: []
},
as: 'itemsAtLocation',
include: [
{
model: Service,
as: 'service',
attributes: ["id"]
},
{
model: Combo,
as: 'combo',
attributes: ["start_date", "expiry_date"]
}
]
}
})
if(!item)
return res.status(200).send({
status: true,
message: "No item found at location!",
data: {}
})
items = item.itemsAtLocation
let data = {}
data.services = []
data.combos = []
_.forEach(items, item => {
let itemData = {
id: item.id,
name: item.name,
price: item.price,
discount_per: item.discount_per,
}
if(item.service)
data.services.push(itemData)
if(item.combo) {
itemData.start_date = item.combo.start_date
itemData.expiry_date = item.combo.expiry_date
data.combos.push(itemData)
}
})
return res.status(200).send({
status: true,
message: "Successfully fetch all items!",
data: data
})
} else {
const items = await Item.findAll({
include: [
{
model: Service,
as: 'service',
attributes: ["id"]
},
{
model: Combo,
as: 'combo',
attributes: ["start_date", "expiry_date"]
}
],
attributes: ["id", "name", "price", "discount_per", "description"],
...paginate(+req.query.page, +req.query.per_page)
})
let data = {}
data.services = []
data.combos = []
_.forEach(items, item => {
let itemData = {
id: item.id,
name: item.name,
price: item.price,
discount_per: item.discount_per,
}
if(item.service)
data.services.push(itemData)
if(item.combo) {
itemData.start_date = item.combo.start_date
itemData.expiry_date = item.combo.expiry_date
data.combos.push(itemData)
}
})
return res.status(200).send({
status: true,
message: "Successfully fetch all items!",
data: data
})
}
}
module.exports = {
getAllItems
}
As you can see from above code. I need queries to return data in a specific form. If it won't be in that form things won't work.
Can someone suggest how can I create stubs for such kind of functions so that structure also be preserved?
Below is the test that I have wrote, But it uses actual db calls.
describe('GET /api/v1/items', function () {
it('should fetch all items orgianized by their type', async () => {
const result = await request(app)
.get('/api/v1/items')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
expect(result)
.to.be.a('Object')
expect(result.body.status)
.to.be.a('Boolean').true
expect(result.body.data, "data should be an Object and every key should an Array")
.to.satisfy(data => {
expect(data).to.be.a('Object')
.to.not.be.null
if(!_.isEmpty(data)) {
expect(data).to.have.any.keys('services', 'combos')
_.forOwn(data, (value, key) => {
expect(data[key]).to.be.a('Array')
})
return true
}
return true
})
})
})
One way you can do that is by stubbing the methods from your models, i.e. Location.findOne and Item.findAll. So your tests could look a bit like the code below:
const sinon = require('sinon');
const Location = require('../models/location'); // Get your location model
const Item = require('../models/item'); // Get your item model
describe('myTest', () => {
let findOneLocationStub;
let findAllItemsStub;
beforeEach(() => {
findOneLocationStub = sinon.stub(Location, 'findOne');
findAllItemsStub = sinon.stub(Item, 'findAll');
});
afterEach(() => {
findOneLocationStub.verifyAndRestore();
findAllItemsStub.verifyAndRestore();
});
it('returns 200 when location not found', () => {
findOneLocationStub.resolves(null);
expects...
});
});
I did not run the test, but something like that should work. But note that I had to split the models into their own file to do the stub. Probably there's a way to do the same using your current implementation.
Another thing I would suggest is having some kind of use case into your method that is responsible for database implementation. Something like:
const getAllItemsUseCase = (params, queryService) => {
if(params.locationId){
let items
const item = await queryService.findOneLocation({
};
So when you call this method from your controller, you can do call:
const getAllItems = async function(req, res) {
const params = {
locationId: req.query.location_id,
// and more parameters
};
const queryService = {
findOneLocation: Location.findOne,
};
const results = await getAllItemsUseCase(params, queryService);
}
This way you will detach your business logic from the controller and you will have a much easier time to mock your query: you just change the methods provided to queryService.
You can find some interesting read from this blog post: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

Resources