forked from tangollama/cis411_lab3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdbutil.js
271 lines (264 loc) · 10.1 KB
/
dbutil.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
const newrelic = require('newrelic')
const { users, locations, bagelTypes } = require('./testdata')
const uuid = require('uuid')
const startCase = require('lodash.startcase')
//lokijs documentation https://rawgit.com/techfort/LokiJS/master/jsdoc/index.html
const loki = require('lokijs')
class Order {
constructor(id, {request_date, location, items, account, source_system}) {
this.id = id;
this.request_date = request_date;
this.location = location;
this.source_system = source_system;
this.account = account; //object
this.items = items; //array of objects
}
}
class Account {
constructor(id, {email, cell, name}) {
this.id = id;
this.email = email;
this.cell = cell;
this.name = name;
}
}
const loadOrder = async (id) => {
return new Promise(resolve => {
newrelic.startSegment('loadOrderById', false, () => {
const orders = db.getCollection("orders")
const accounts = db.getCollection("accounts")
//Object.assign to ensure we're not creating circular references
const order = Object.assign({}, orders.findOne( {'id':id}))
if (order) {
const account = accounts.findOne( { 'id': order.account_id })
order.customer = account
order.dateLastOpened = new Date().getTime()
orders.update(order)
}
resolve(order)
})
})
}
const queryOrders = async (args) => {
const { query, location, bagel } = args
if (location) {
return new Promise(resolve => {
newrelic.startSegment('queryOrdersByLocation', false, () => {
const orders = db.getCollection("orders")
const accounts = db.getCollection("accounts")
const results = orders.find({ 'location': location })
results.forEach(element => {
if (element.account_id) {
//Object.assign to ensure we're not creating circular references
element.customer = Object.assign({}, accounts.findOne({ 'id': element.account_id}))
}
})
resolve(results)
})
})
} else if (bagel) {
return new Promise(resolve => {
newrelic.startSegment('queryOrdersByBagelType', false, () => {
const orders = db.getCollection("orders")
const accounts = db.getCollection("accounts")
const results = orders.find({ 'items.type': { '$contains': bagel } })
results.forEach(element => {
if (element.account_id) {
//Object.assign to ensure we're not creating circular references
element.customer = Object.assign({}, accounts.findOne({ 'id': element.account_id}))
}
})
resolve(results)
})
})
} else if (query) {
return new Promise(resolve => {
newrelic.startSegment('queryOrdersBySearchTerm', false, () => {
const orders = db.getCollection("orders")
const accounts = db.getCollection("accounts")
const ids = orders.find({
'$or': [
{
'id' : {
'$contains': query
}
},{
'request_date' : {
'$contains': query
}
},{
'location' : {
'$contains': query
}
},{
'source' : {
'$contains': query
}
},{
'items.type' : {
'$contains': query
}
},{
'items.label' : {
'$contains': query
}
}
]
})
const results = ids.map((result) => {
return loadOrder(result.id)
})
resolve(results)
})
})
} else {
return new Promise(resolve => {
newrelic.startSegment('queryOrdersOpen', false, () => {
const orders = db.getCollection("orders")
const accounts = db.getCollection("accounts")
//return the entire database... this is probably going to take a moment.
const results = orders.chain().data()
results.forEach(element => {
if (element.account_id) {
//Object.assign to ensure we're not creating circular references
element.customer = Object.assign({}, accounts.findOne({ 'id': element.account_id}))
}
})
resolve(results)
})
})
}
}
const upsertOrder = async (input) => {
if (input.id) {
return new Promise(resolve => {
newrelic.startSegment('updateOrder', false, () => {
const orders = db.getCollection("orders")
var order = orders.findOne({ 'id': input.id })
order = Object.assign(order, input)
orders.update(order)
resolve(order)
})
})
} else {
return new Promise(resolve => {
newrelic.startSegment('insertOrder', false, () => {
const orders = db.getCollection("orders")
input.id = uuid()
input.dateLastOpened = null
resolve(orders.insert(input))
})
})
}
}
const loadAccount = async (id) => {
return new Promise(resolve => {
newrelic.startSegment('loadAccount', false, () => {
const accounts = db.getCollection("accounts")
const orders = db.getCollection("orders")
//Object.assign to ensure we're not creating circular references
const account = Object.assign({}, accounts.findOne( {'id':id} ))
const myOrders = orders.find({ 'account_id':id })
account.orders = myOrders
resolve(account)
})
})
}
const queryAccounts = async (query) => {
if (query) {
return new Promise(resolve => {
newrelic.startSegment('queryAccountsBtSearchTerm', false, () => {
const accountsCollection = db.getCollection("accounts")
const accounts = accountsCollection.find({'$or': [{
'email' : {
'$contains': query
}
},{
'name' : {
'$contains': query
}
}]})
resolve(accounts)
})
})
} else {
return new Promise(resolve => {
newrelic.startSegment('queryAccountsBtSearchTerm', false, () => {
const accountsCollection = db.getCollection("accounts")
resolve(accountsCollection.chain().simplesort("name").data())
})
})
}
}
const upsertAccount = async (input) => {
if (input.id) {
return new Promise(resolve => {
newrelic.startSegment('updateAccount', false, () => {
const accounts = db.getCollection("accounts")
var account = accounts.findOne({ 'id': input.id })
account = Object.assign(account, input)
accounts.update(account)
resolve(account)
})
})
} else {
return new Promise(resolve => {
newrelic.startSegment('insertAccount', false, () => {
const accounts = db.getCollection("accounts")
input.id = uuid()
resolve(accounts.insert(input))
})
})
}
}
const deleteAccount = async (id) => {
return new Promise(resolve => {
newrelic.startSegment('insertAccount', false, () => {
const accounts = db.getCollection("accounts")
var account = accounts.findOne({ 'id': id})
accounts.remove(account)
resolve()
})
})
}
const db = new loki('bagels.db', {
autoload: true,
autoloadCallback : _dbInit,
autosave: true,
autosaveInterval: 4000
})
function _dbInit() {
var accounts = db.getCollection("accounts")
if (!accounts) {
accounts = db.addCollection("accounts")
users.forEach(user => {
upsertAccount(user)
})
db.saveDatabase()
}
var orders = db.getCollection("orders")
if (!orders) {
orders = db.addCollection("orders")
for (var i = 0; i < 100000; i++) {
const location = locations[Math.floor((Math.random() * locations.length))]
const bagelType = bagelTypes[Math.floor((Math.random() * bagelTypes.length))]
const account_id = users[Math.floor((Math.random() * users.length))].id
const order = {
request_date: new Date('2018', '11', Math.floor((Math.random() * 30)+1)),
location: location,
items: [ {
label: startCase(bagelType),
type: bagelType,
quantity: Math.floor((Math.random() * 5)+1),
perUnitPrice: 2.50
}],
account_id: account_id,
source_system: 'dataload'
}
upsertOrder(order)
}
}
db.saveDatabase()
console.log(`Accounts: ${accounts.count()} Orders: ${orders.count()}`)
}
module.exports = { loadOrder, queryOrders, upsertOrder, loadAccount, upsertAccount, deleteAccount, queryAccounts, Order, Account };