Vish2005 commited on
Commit
9dfef10
1 Parent(s): f00d2b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -123
app.py CHANGED
@@ -134,189 +134,147 @@ def query_to_SQL_to_MongoDB(query, key, organization):
134
  return complex_SQL_to_MongoDB(SQL)
135
 
136
 
137
- keywords = {'INNER', 'FROM', 'WHERE', 'GROUP', 'BY', 'ON', 'SELECT', 'BETWEEN', 'LIMIT', 'AND', 'ORDER'}
138
-
139
- mapper = {} # maps SQL symbols to MongoDB functions
140
-
141
- mapper['<'] = '$lt'
142
- mapper['>'] = '$gt'
143
- mapper['!='] = '$ne'
144
 
145
  def complex_SQL_to_MongoDB(query):
146
 
 
 
 
 
 
 
147
  query = re.split(r' |\n', query) # split the query on spaces and turn in to array
148
- query = [ x for x in query if len(x) > 0]
 
 
 
 
 
 
149
 
150
- if len(query[0]) > 3 and (query[0][:3] == 'MAX' or query[0][:3] == 'MIN'):
 
 
 
 
 
 
 
 
151
 
152
  query += ['ORDER', 'BY', query[0][4:-1], 'DESC' if query[0][:3] == 'MAX' else 'ASC', 'LIMIT', '1']
153
 
154
- count_str = ''
155
 
156
- if len(query[0]) > 5 and query[0][:5] == 'COUNT':
157
 
158
- count_str += ' {$count : '
159
  if query[0][6] == '*':
160
 
161
- count_str += '{} }'
162
 
163
  else:
164
 
165
- count_str += query[0][6:-1] + ' }'
166
 
167
- print(query)
168
- fields = ''
169
- i = 0
170
- while query[i] != 'FROM':
171
 
172
- fields += ' ' + query[i] + ' : 1,'
173
  i += 1
174
 
175
- fields = fields[:-1]
176
- i = i +1
177
- collection = query[i]
178
  i = i + 1
179
- if i < len(query) and query[i] not in keywords:
180
 
181
  i += 1
182
  answer = 'db.' + collection + ".aggregate( " # MongoDB function for aggregation
183
 
184
- while i < len(query) and query[i] == 'INNER':
185
 
186
- i = i + 2
187
- lookup = '{$lookup: { from : "'
188
- lookup += query[i] + '", localField: "'
189
- if query[i+1] not in keywords:
190
  i += 1
191
  i = i + 2
192
- lookup += query[i].split('.')[1] + '", foreignField: "'
193
- i = i+2
194
- lookup += query[i].split('.')[1] + '", as: "' + collection + '"} },'
195
  i = i + 1
196
- answer += lookup
197
 
198
 
199
- if i < len(query) and query[i] == 'WHERE':
200
 
201
- where = '{$match:'
202
- count = 0
 
203
 
204
  while i < len(query) and (query[i] == 'WHERE' or query[i] == 'AND'):
205
 
206
- count += 1
207
  i = i+1
208
- conditions = ''
209
- print(query[i])
210
- conditions = '{' + (query[i].split('.')[1] if len(query[i].split('.')) > 1 else query[i] ) + " : "
211
- if query[i+1] == '=':
212
 
213
  conditions += query[i+2]
214
  i = i + 3
215
 
216
- elif query[i+1] == 'BETWEEN':
217
 
218
  conditions += '{$gt: ISODate(' + query[i+2] + '), $lt: ISODate(' + query[i+4] + ')}'
219
  i+= 5
220
 
221
- else:
222
 
223
  conditions += '{ ' + mapper[query[i+1]] + ' : ' + query[i+2] + ' }'
224
  i = i+3
225
 
226
- conditions += '},'
227
 
228
- if count > 1:
229
 
230
- where += '{ $and: [' + conditions[:-1] + ']}}'
231
 
232
  else:
233
 
234
- where += conditions[:-1] + '}, '
235
 
236
- answer += where
237
 
238
 
239
- if i < len(query) and (query[i] == 'GROUP' or query[i] == 'ORDER'):
240
 
241
  i = i + 2
242
- group = '{$group: { _id: "' + query[i] + '"'
243
  i += 1
244
- i -= 3 if query[i -3 ] == 'ORDER' else 0
245
- if query[i] == 'ORDER' and len(query[i+2]) > 5 and query[i+2][0:5] == 'COUNT':
246
 
247
- group += ', count: {$count: ' + ('{}' if query[i+2].split('(')[1][:-1] == '*' else ('{' + query[i+2].split('(')[1][:-1].split('.')[1] + '}') ) + '} }}, { $sort: {count : ' + ('1' if query[i+3] == 'ASC' else '-1') + '}}, '
248
 
249
- else:
250
 
251
  group += '} }, { $sort: {' + query[i+2] + ' : ' + ('1' if query[i+3] == 'ASC' else '-1') + '}},'
252
 
253
- i += 4
254
-
255
- answer += group
256
-
257
- if i < len(query) and query[i] == 'LIMIT':
258
-
259
- answer += '{ $limit : ' + query[i+1] + ' }, '
260
-
261
- answer += count_str
262
- answer += ')'
263
-
264
- return answer
265
-
266
-
267
- def simple_SQL_to_MongoDB(query): #ignore function as it is replaced by new complex version
268
-
269
- query = query.split(' ') # split the query on spaces and turn in to array
270
- query = query[1:] # remove the initial space
271
- answer = 'db.collection.find' # MongoDB function for selection
272
- fields = ''
273
- i = 0
274
- while query[i] != 'FROM':
275
 
276
- fields += ' ' + query[i] + ' : 1,'
277
- i += 1
278
-
279
- fields = fields[:-1]
280
- while query[i] != 'WHERE':
281
-
282
- i += 1
283
-
284
- i += 1
285
- conditions = ''
286
- while i+2 < len(query):
287
-
288
- print(i)
289
-
290
- conditions += ' ' + query[i] + ' : '
291
- if query[i+1] == '=':
292
-
293
- conditions += query[i+2]
294
-
295
- elif query[i+1] == 'BETWEEN':
296
-
297
- conditions += '{$gt: ISODate(' + query[i+2] + '), $lt: ISODate(' + query[i+4] + ')}'
298
- i+= 6
299
- conditions += ','
300
- continue
301
-
302
- else:
303
-
304
- conditions += '{ ' + mapper[query[i+1]] + ' : ' + query[i+2] + ' }'
305
-
306
- conditions += ','
307
-
308
- i+= 4
309
 
310
-
311
 
312
-
313
 
314
- conditions = conditions[:-1]
315
 
 
 
 
316
 
317
- answer += '({' + conditions + '}, {' + fields + '})'
318
 
319
- return answer
320
 
321
  """# Main method"""
322
 
@@ -343,17 +301,7 @@ def query_creator(key, organization, plain_query):
343
  MongoDB_query = query_to_SQL_to_MongoDB(modified_query, key, organization)
344
  return MongoDB_query
345
 
346
- """#Testers of query creator"""
347
-
348
- tests = ["giv me number of orders from the driver elizbeth", "name of driver with maximum ordres", "first two orders with the highest order amount", "address of customer with lowest ordr amount",\
349
- "id of customer with most complints", "date of customer support with sales id 21695-828", "number of drivers with order amount 20", "numbser of orders by customer martha", "order amount of most recent customer support",\
350
- "amount of the highest order by customber Federica"]
351
-
352
- #for test in tests:
353
-
354
- # print(query_creator(api_key, org_key, test)) # put in your api and org keys to use the tester
355
 
356
- """# UI"""
357
 
358
  iface = gr.Interface(fn=query_creator, inputs= [gr.Textbox(label = "API Key"), gr.Textbox(label = "Organization Key"), gr.Textbox(label = "Plain Text Query")], outputs=gr.Textbox(label = "MongoDB Query"), )
359
  iface.launch()
 
134
  return complex_SQL_to_MongoDB(SQL)
135
 
136
 
 
 
 
 
 
 
 
137
 
138
  def complex_SQL_to_MongoDB(query):
139
 
140
+ keywords = {'INNER', 'FROM', 'WHERE', 'GROUP', 'BY', 'ON', 'SELECT', 'BETWEEN', 'LIMIT', 'AND', 'ORDER'} # keyword set used by my MongoDB function
141
+ mapper = {} # maps SQL symbols to MongoDB functions
142
+ mapper['<'] = '$lt'
143
+ mapper['>'] = '$gt'
144
+ mapper['!='] = '$ne'
145
+
146
  query = re.split(r' |\n', query) # split the query on spaces and turn in to array
147
+ query = [ x for x in query if len(x) > 0] # remove empty strings in the array
148
+
149
+ while query[0][:3] not in ['MAX', 'MIN'] and query[0][:5] != 'COUNT' and query[0] not in keywords:
150
+
151
+ query = query[1:]
152
+
153
+ if query[1] == 'AS':
154
 
155
+ rename = query[2]
156
+
157
+ for i in range(3, len(query)):
158
+
159
+ if query[i] == rename:
160
+
161
+ query[i] = query[0]
162
+
163
+ if len(query[0]) > 3 and (query[0][:3] == 'MAX' or query[0][:3] == 'MIN'): # if the SQL contains a MAX or MIN select then we rewrite the SQL query in an easier format
164
 
165
  query += ['ORDER', 'BY', query[0][4:-1], 'DESC' if query[0][:3] == 'MAX' else 'ASC', 'LIMIT', '1']
166
 
167
+ count_str = '' # builds a MongoDB statement if there is a count in the select statement
168
 
169
+ if len(query[0]) > 5 and query[0][:5] == 'COUNT': # if there is indeed a count
170
 
171
+ count_str += ' {$count : ' # construct the count sequence
172
  if query[0][6] == '*':
173
 
174
+ count_str += '{} }' # an asterisk means everything
175
 
176
  else:
177
 
178
+ count_str += query[0][6:-1] + ' }' # otherwise write the actual field it wants
179
 
180
+ count_str += ','
181
+ i = 0 # iterator variable
182
+ while query[i] != 'FROM': # as long as we are still in the select continue because you cannot do select in db.Aggregate
 
183
 
 
184
  i += 1
185
 
186
+ i = i +1 # ignore the FROM
187
+ collection = query[i] # table from which the information will be taken
 
188
  i = i + 1
189
+ if i < len(query) and query[i] not in keywords: # sometimes SQL queries rename tables but we ignore that in MongoDB
190
 
191
  i += 1
192
  answer = 'db.' + collection + ".aggregate( " # MongoDB function for aggregation
193
 
194
+ while i < len(query) and query[i] == 'INNER': # if there is an inner join
195
 
196
+ i = i + 2 # ignore the keywords
197
+ lookup = '{$lookup: { from : "' # MongoDB structure
198
+ lookup += query[i] + '", localField: "' # specifies home key
199
+ if query[i+1] not in keywords: # skip renaming of tables
200
  i += 1
201
  i = i + 2
202
+ lookup += query[i].split('.')[1] + '", foreignField: "' # specifies foreign key
203
+ i = i+2
204
+ lookup += query[i].split('.')[1] + '", as: "' + collection + '"} },' # rename final table to the original table
205
  i = i + 1
206
+ answer += lookup # add this to the MongoDB query
207
 
208
 
209
+ if i < len(query) and query[i] == 'WHERE': # if there is a WHERE clause
210
 
211
+ where = '{$match:' # MongoB keyword
212
+ count = 0 # tells us if there is an AND in the where clause
213
+ conditions = '' # stores the actual conditions required
214
 
215
  while i < len(query) and (query[i] == 'WHERE' or query[i] == 'AND'):
216
 
217
+ count += 1 # add one every time you find a where matching
218
  i = i+1
219
+ conditions += '{' + (query[i].split('.')[1] if len(query[i].split('.')) > 1 else query[i] ) + " : " # format to MongoDB
220
+ if query[i+1] == '=': # if there is an equality then use a colon
 
 
221
 
222
  conditions += query[i+2]
223
  i = i + 3
224
 
225
+ elif query[i+1] == 'BETWEEN': # if there are dates then use the specified date format
226
 
227
  conditions += '{$gt: ISODate(' + query[i+2] + '), $lt: ISODate(' + query[i+4] + ')}'
228
  i+= 5
229
 
230
+ else: # else use the mapper function to map the write symbol here
231
 
232
  conditions += '{ ' + mapper[query[i+1]] + ' : ' + query[i+2] + ' }'
233
  i = i+3
234
 
235
+ conditions += '},' # end the conditions
236
 
237
+ if count > 1: # if you have been in there for more than once then
238
 
239
+ where += '{ $and: [' + conditions[:-1] + ']}}' # use the AND version of MongoDB
240
 
241
  else:
242
 
243
+ where += conditions[:-1] + '},' # otherwise end the clause
244
 
245
+ answer += where # add this to the final query
246
 
247
 
248
+ if i < len(query) and (query[i] == 'GROUP' or query[i] == 'ORDER'): # if there is a Group BY or Order BY
249
 
250
  i = i + 2
251
+ group = '{$group: { _id: "' + query[i] + '"' # in any case, you use group in MongoDB
252
  i += 1
253
+ i -= 3 if query[i -3 ] == 'ORDER' else 0 # depending on which one you continue
254
+ if i < len(query) and query[i] == 'ORDER' and len(query[i+2]) > 5 and query[i+2][0:5] == 'COUNT': # if there is an order by with count
255
 
256
+ group += ', count: {$count: ' + ('{}' if query[i+2].split('(')[1][:-1] == '*' else ('{' + query[i+2].split('(')[1][:-1].split('.')[1] + '}') ) + '} }}, { $sort: {count : ' + ('1' if query[i+3] == 'ASC' else '-1') + '}},'
257
 
258
+ elif i < len(query) and query[i] == 'ORDER': # if there is an order by without count
259
 
260
  group += '} }, { $sort: {' + query[i+2] + ' : ' + ('1' if query[i+3] == 'ASC' else '-1') + '}},'
261
 
262
+ else:group += '} },' # if there is no orde by and only group
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
+ i += 4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
+ answer += group # add answer to group
267
 
268
+ if i < len(query) and query[i] == 'LIMIT': # if there is a limit then add that too
269
 
270
+ answer += '{ $limit : ' + query[i+1] + ' },'
271
 
272
+ answer += '' if count_str == ',' else count_str# finally add back any count command
273
+ answer = answer[:-1]
274
+ answer += ')' # end the whole query
275
 
276
+ return answer # return
277
 
 
278
 
279
  """# Main method"""
280
 
 
301
  MongoDB_query = query_to_SQL_to_MongoDB(modified_query, key, organization)
302
  return MongoDB_query
303
 
 
 
 
 
 
 
 
 
 
304
 
 
305
 
306
  iface = gr.Interface(fn=query_creator, inputs= [gr.Textbox(label = "API Key"), gr.Textbox(label = "Organization Key"), gr.Textbox(label = "Plain Text Query")], outputs=gr.Textbox(label = "MongoDB Query"), )
307
  iface.launch()