how to sum of all user orders in typeorm - node.js-typeorm

const query = getManager()
.createQueryBuilder(Users, 'user')
.addSelect("SUM(user.orders)", "totalOrders")
.groupBy("user.id");
this code is not working

const query = getManager()
.createQueryBuilder(Users, 'user')
.where('user.userType = :userType', { userType: 'user' })
.loadRelationCountAndMap("user.totalorders", "user.orders")
.groupBy("user.id");
note:-
user.totalOrders=this is aliases
user.orders=this is Table colum name

Related

How can I use AQL with multiple queries that using the result of one another?

I have 2 vertices and an edge named user, device, ownership respectively.
My business logic is when I receive device information, I upsert it with dateCreated and dateUpdated fields added. If I inserted that device then I insert new user with default values and create edge connection to it. If I update I simple return already connected user as a result.
Without losing atomicity how can I achieve this?
I tried single AQL query but without condition it is not possible it seems and traversal also is not supported with insert/update operation.
I can do separate queries but that loses atomicity.
var finalQuery = aql`
UPSERT ${deviceQuery}
INSERT MERGE(${deviceQuery},{dateCreated:DATE_NOW()})
UPDATE MERGE(${deviceQuery},{dateUpdated:DATE_NOW()})
IN ${this.DeviceModel}
RETURN { doc: NEW, type: OLD ? 'update' : 'insert' }`;
var cursor = await db.query(finalQuery);
var result = await cursor.next();
if (result.type == 'insert') {
console.log('Inserted documents')
finalQuery = aql`
LET user=(INSERT {
"_key":UUID(),
"name": "User"
} INTO user
RETURN NEW)
INSERT {
_from:${result.doc._id},
_to:user[0]._id,
"type": "belongs"
}INTO ownership
return user[0]`;
cursor = await db.query(finalQuery);
result = await cursor.next();
console.log('New user:',result);
}
You can try something like this
Upsert ....
FILTER !OLD
Let model = NEW
LET user= First(INSERT {
"_key":UUID(),
"name": "User"
} INTO user
RETURN NEW)
INSERT {
_from:model._id,
_to:user._id,
"type": "belongs"
}INTO ownership
return user
I end up separating the modification and selection queries.
var finalQuery = aql`
LET device=(
UPSERT ${deviceQuery}
INSERT MERGE(${deviceQuery},{dateCreated:DATE_NOW()})
UPDATE MERGE(${deviceQuery},{dateUpdated:DATE_NOW()})
IN ${this.DeviceModel}
RETURN { doc: NEW, type: OLD ? 'update' : 'insert' })
FILTER device[0].type=='insert'
LET user=(INSERT {
"_key":UUID(),
"name": "User"
} INTO user
RETURN NEW)
INSERT {
_from:device[0].doc._id,
_to:user[0]._id,
"type": "belongs"
}INTO ownership
return user[0]`;
var cursor = await db.query(finalQuery);
var result = await cursor.next();
if (result == null) {
const deviceId=this.DeviceModel.name+"/"+queryParams._key;
finalQuery = aql`
FOR v,e,p IN 1..1
OUTBOUND ${deviceId} ownership
FILTER e.type=="belongs"
RETURN v `;
cursor = await db.query(finalQuery);
result = await cursor.next();
isUpdate=true;
}
This way I ensure the atomicity. There are improvements for controling if cursor.extra.stats.writesExecuted true etc.

How to get Max() Value using linq

I have two table cost and history table, both table have the same field name AccountingMonth, i would like to get Latest AccountingMonth from the two table
var accountingMonthCost= await _context.Cost
.Select(ic => new ProductDTO
{
LatestCostMonth = ic.AccountingMonth
})
.ToListAsync();
History table
var accountingMonthHistory = await _context.history
.Select(ic => new ProductDTO
{
LatestCostMonth = ic.AccountingMonth
})
.ToListAsync();
I need help combine AccountingMonth in both table and get the latest Accounting Month.
Concat both together and ask for the max.
var latestAccountingMonth = await _context.Cost.Select(c=>c.AccountingMonth)
.Concat(_context.history.Select(c=>c.AccountingMonth))
.MaxAsync();

Avoid duplicating fieldPath's when updating or creating documents in Firestore

Are there any way's to avoid duplicating strings everywhere when using TypeScript in Cloud Functions in Firebase?
I've tried making them enums, and that goes a long way.
enum Collections {
SUBSCRIPTIONS = 'subscriptions-dev',
ACTIVITIES = 'activity-dev'
}
enum ActivityKey {
SUBSCRIPTION = 'sub',
GROUP_ACTIVITY_ID = 'groupActivityId',
GROUP_ACTIVITY_BOOKING_ID = 'groupActivityBookingId',
ACTIVITY_NAME = 'activityName',
ACTIVITY_START = 'activityStart',
BOOKABLE_EARLIEST = 'bookableEarliest',
BOOKABLE_LATEST = 'bookableLatest',
STATE = 'state'
};
Then I can for example do:
const activityRef = admin.firestore().collection(Collections.ACTIVITIES);
return await Promise.all(subscriptions.map(async (subscriptionDocument) => {
const sub = await subscriptionDocument.get();
const groupActivityProductId = sub.get(SubscriptionKey.GROUP_ACTIVITY_PRODUCT_ID);
const refreshToken = sub.get(SubscriptionKey.REFRESH_TOKEN);
...
Now here's the problem, when I want to create or update keypaths, using set() or update() functions, it expects a dictionary - and I can't use the enums as keys in dictionaries.
await activityRef.doc().set({
sub: sub.ref,
groupActivityId: activity.id,
activityStart: new Date(activity.duration.start),
bookableEarliest: new Date(activity.bookableEarliest),
bookableLatest: new Date(activity.bookableLatest),
instructor: activity.instructors.empty ? "-" : activity.instructors[0].name,
lastChecked: new Date(),
activityName: activity.name,
state: ActivityState.NEW
})
If I write ActivityKey.SUBSCRIPTION as key, I get ',' expected ts(1005)
I've actually found the answer myself!
If I wrap the key in [], like this:
await activityRef.doc().set({
[ActivityKey.SUBSCRIPTION]: sub.ref,
[ActivityKey.GROUP_ACTIVITY_ID]: activity.id,
[ActivityKey.ACTIVITY_START]: new Date(activity.duration.start),
[ActivityKey.BOOKABLE_EARLIEST]: new Date(activity.bookableEarliest),
[ActivityKey.BOOKABLE_LATEST]: new Date(activity.bookableLatest),
[ActivityKey.INSTRUCTOR]: activity.instructors.empty ? "-" : activity.instructors[0].name,
[ActivityKey.LAST_CHECKED]: new Date(),
[ActivityKey.ACTIVITY_NAME]: activity.name,
[ActivityKey.STATE]: ActivityState.NEW,
[ActivityKey.HAS_SENT_CANCEL_REMINDER]: false
})
It works!

In sequelize, how to query the model associated with 'through'

I am very new to Sequelize and need help to create a method to query between two tables.
I have given three models named "user", "project" and "user_project".
user_project stores the relationship between users and projects. It uses two foreign keys (user_id and project_id) from other tables.
In addition, user_project has a field named "role" to specify the role of the user in a project. I am trying to figure out a way to extract user roles based on user "email". Note than user email is stored in user table.
The associations between them are as follows:
models.project.belongsToMany(models.user, {
through: models.user_project,
foreignKey: {
name: 'projectId',
field: 'project_id'
}
});
models.user.belongsToMany(models.project, {
through: models.user_project,
foreignKey: {
name: 'userId',
field: 'user_id'
}
});
Thanks in advance.
Know this is very late but hope it will someone else in future -
Using raw query and then converting the roles string to array -
User.findOne({
where: {email},
attributes: [
'id', 'email',
[Sequelize.literal("(SELECT GROUP_CONCAT(roles) FROM user_project UP WHERE UP.user_id=user.id )"), "roles"],
]
}).then( (user) => {
if(!user)
return null;
user = JSON.parse(JSON.stringify(user));
if(!user.roles)
user.roles = [];
else
user.roles = user.roles.split(",");
return user;
});
Getting roles without Using Raw -
User.findOne({
where: {email},
attributes: [
'id', 'email'
],
include: [
{
model: Db.user_project,
required: false,
attributes: ["user_id", "roles"]
}
]
}).then( (user) => {
if(!user)
return null;
user = JSON.parse(JSON.stringify(user));
if(!user.roles)
user.roles = [];
else
user.roles = user.roles.map(r => r.roles);
return user;
});

How to load multiple data via service and wait for it in Angular2

I use Ionic 2 with Angular 2 in my project. In the root component you can click a "Add" button to add a new Report via a complex form and a lot of preprovided data (there are some selects that are feeded with data fetched from sqlite database)
Now in my "CreateReportComponent" i have the following constructor to load the data and assign it to local array variable:
selectEmployeeOptions: Employee[];
constructor(private dbService: DatabaseService) {
dbService.getAllEmployees().then(employees => {
this.selectEmployeeOptions = employees;
});
// load more data like tasks etc.
});
But when I want to modify this data in my component, the array is empty. I tried to do it in ngOnInit() but this seems to be to early as well.
I want to to something like this, before the component gets displayed:
dbService.getAllEmployees().then(employees => {
this.selectEmployeeOptions = employees;
// modify data
this.selectEmployeeTitleOptions = employees.map((item) => {
return item.title;
});
console.log(JSON.stringify(this.selectEmployeeTitleOptions)) // --> empty
});
But selectEmployeeTitleOptions is empty...
The function in the databaseService looks like this:
getAllEmployees(): Promise<Emplyoee[]> {
let query = "SELECT * FROM employees";
let employeeList = [];
this.database.executeSql(query, []).then((data) => {
if(data.rows.length > 0) {
let e = new Employee();
e.id = data.rows.item(i).id;
e.firstname = data.rows.item(i).firstname;
e.lastname = data.rows.item(i).lastname;
employeeList.push(e);
}
}, (error) => {
// handle error
});
return Promise.resolve(employeeList);
}
I read that there is the Resolve pattern (https://blog.thoughtram.io/angular/2016/10/10/resolving-route-data-in-angular-2.html) But I need to make multiple calls and not only for contacts as in the example.
So the question: How to wait for multiple calls to database?
i think something go wrong here
getAllEmployees(): Promise<Emplyoee[]> {
let query = "SELECT * FROM employees";
let employeeList = [];
this.database.executeSql(query, []).then((data) => {
if(data.rows.length > 0) {
let e = new Employee();
e.id = data.rows.item(i).id;
e.firstname = data.rows.item(i).firstname;
e.lastname = data.rows.item(i).lastname;
employeeList.push(e);
}
}, (error) => {
// handle error
});
return Promise.resolve(employeeList);
}
first return Promise.resolve(employeeList); will return empty array, because it is async process.
you need loop through data.rows, then format return data like this.
getAllEmployees(): Promise<Employee[]> {
let query = "SELECT * FROM employees";
return this.database.executeSql(query, []).then((data) => {
let arr = [];
for(let i = ; i < data.rows.length; ++i) {
let emp = data.rows.item(i);
let e = new Employee();
e.id = emp.id;
e.firstname = emp.firstname;
e.lastname = emp.lastname;
arr.push(e);
}
return arr;
});
}
note that .then() return a promise object.
What you are looking for is forkJoin method that returns Observable that you should switch to instead of using Promises, for reference about why you should do this check here.
Short information about fork join from its GitHub page:
Runs all observable sequences in parallel and collect their last elements.
This way you can safely make parallel requests to your API.
For more information regarding forkJoin go here.
Additionally you should call services using ngOnInit as you mentioned before. For more information about Angular 2 lifecycle hooks see the docs.
You can use Promise.all
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
You push all promises to an array, and then go
let foo : [Promise<Emplyoee[]>,Promise<void>] = [getAllEmployees(), method2()];
Promise.all(foo).then((results:any[]) => {
let employeearray: any = results[0];
/* and on an on */
});

Resources