openbel-api 0.5.1-java → 0.6.1-java

Sign up to get free protection for your applications and to get access to all the features.
data/config/config.yml CHANGED
@@ -51,12 +51,10 @@ resource_search:
51
51
  # Set a secret used during session creation....
52
52
  session_secret: 'changeme'
53
53
 
54
- # User authentication using Auth0.
54
+ # User authentication via JWTs; see http://jwt.io/introduction/ for more
55
55
  auth:
56
+ # Controls whether the API requires authentication
56
57
  enabled: false
57
- redirect: 'https://openbel.auth0.com/authorize?response_type=code&scope=openid%20profile&client_id=K4oAPUaROjbWWTCoAhf0nKYfTGsZWbHE'
58
- default_connection: 'linkedin'
59
- domain: 'openbel.auth0.com'
60
- id: 'K4oAPUaROjbWWTCoAhf0nKYfTGsZWbHE'
61
- # secret: 'auth0 client secret here'
58
+ # Used by the auth middleware to decode and verify the JWT
59
+ #secret: 'JWT secret here'
62
60
 
@@ -15,6 +15,14 @@ module OpenBEL
15
15
  fail NotImplementedError, "#{__method__} is not implemented"
16
16
  end
17
17
 
18
+ def find_all_namespace_references
19
+ fail NotImplementedError, "#{__method__} is not implemented"
20
+ end
21
+
22
+ def find_all_annotation_references
23
+ fail NotImplementedError, "#{__method__} is not implemented"
24
+ end
25
+
18
26
  def count_evidence(filters = [])
19
27
  fail NotImplementedError, "#{__method__} is not implemented"
20
28
  end
@@ -72,11 +72,11 @@ module OpenBEL
72
72
  end
73
73
 
74
74
  def make_filter(category, name, value)
75
- MultiJson.dump({
75
+ {
76
76
  :category => category,
77
77
  :name => name,
78
- :value => value,
79
- })
78
+ :value => value
79
+ }
80
80
  end
81
81
  end
82
82
  end
@@ -1,4 +1,5 @@
1
1
  require 'bel'
2
+ require 'bel/evidence_model/util'
2
3
  require 'mongo'
3
4
  require_relative 'api'
4
5
  require_relative 'mongo_facet'
@@ -11,10 +12,15 @@ module OpenBEL
11
12
  include Mongo
12
13
 
13
14
  def initialize(options = {})
14
- host = options[:host]
15
- port = options[:port]
16
- db = options[:database]
17
- @db = MongoClient.new(host, port).db(db)
15
+ host = options[:host]
16
+ port = options[:port]
17
+ db = options[:database]
18
+ @db = MongoClient.new(
19
+ host,
20
+ port,
21
+ :op_timeout => nil,
22
+ :pool_size => 30
23
+ ).db(db)
18
24
 
19
25
  # Authenticate user if provided.
20
26
  username = options[:username]
@@ -25,15 +31,10 @@ module OpenBEL
25
31
  end
26
32
 
27
33
  @collection = @db[:evidence]
28
- @collection.ensure_index(
29
- {:"bel_statement" => Mongo::ASCENDING },
30
- :background => true
31
- )
32
- @collection.ensure_index(
33
- {:"$**" => Mongo::TEXT },
34
- :background => true
35
- )
36
34
  @evidence_facets = EvidenceFacets.new(options)
35
+
36
+ # ensure all indexes are created and maintained
37
+ ensure_all_indexes
37
38
  end
38
39
 
39
40
  def create_evidence(evidence)
@@ -55,29 +56,16 @@ module OpenBEL
55
56
  @collection.find_one(to_id(value))
56
57
  end
57
58
 
58
- def find_evidence(filters = [], offset = 0, length = 0, facet = false)
59
- query_hash = to_query(filters)
60
- query_opts = query_options(
61
- query_hash,
62
- :skip => offset,
63
- :limit => length,
64
- :sort => [
65
- [:bel_statement, :asc]
66
- ]
67
- )
68
-
69
- results = {
70
- :cursor => @collection.find(query_hash, query_opts)
71
- }
72
- if facet
73
- facets_doc = @evidence_facets.find_facets(query_hash, filters)
74
- results[:facets] = facets_doc["facets"]
59
+ def find_evidence(filters = [], offset = 0, length = 0, facet = false, facet_value_limit = -1)
60
+ if includes_fts_search?(filters)
61
+ text_search = get_fts_search(filters)
62
+ evidence_aggregate(text_search, filters, offset, length, facet, facet_value_limit)
63
+ else
64
+ evidence_query(filters, offset, length, facet, facet_value_limit)
75
65
  end
76
-
77
- results
78
66
  end
79
67
 
80
- def find_dataset_evidence(dataset, filters = [], offset = 0, length = 0, facet = false)
68
+ def find_dataset_evidence(dataset, filters = [], offset = 0, length = 0, facet = false, facet_value_limit = -1)
81
69
  query_hash = to_query(filters)
82
70
  query_hash[:$and] ||= []
83
71
  query_hash[:$and].unshift({
@@ -97,13 +85,124 @@ module OpenBEL
97
85
  :cursor => @collection.find(query_hash, query_opts)
98
86
  }
99
87
  if facet
100
- facets_doc = @evidence_facets.find_facets(query_hash, filters)
101
- results[:facets] = facets_doc["facets"]
88
+ facets_cursor = @evidence_facets.find_facets(query_hash, filters, facet_value_limit)
89
+ results[:facets] = facets_cursor.to_a
102
90
  end
103
91
 
104
92
  results
105
93
  end
106
94
 
95
+ def find_all_namespace_references
96
+ references = @collection.aggregate(
97
+ [
98
+ {
99
+ :$project => {
100
+ "references.namespaces" => 1
101
+ }
102
+ },
103
+ {
104
+ :$unwind => "$references.namespaces"
105
+ },
106
+ {
107
+ :$project => {
108
+ keyword: "$references.namespaces.keyword",
109
+ uri: "$references.namespaces.uri"
110
+ }
111
+ },
112
+ {
113
+ :$group => {
114
+ _id: "$keyword", uri: {
115
+ :$addToSet => "$uri"
116
+ }
117
+ }
118
+ },
119
+ {
120
+ :$unwind => "$uri"
121
+ },
122
+ {
123
+ :$project => {
124
+ keyword: "$_id", uri: "$uri", _id: 0
125
+ }
126
+ }
127
+ ],
128
+ {
129
+ allowDiskUse: true,
130
+ cursor: {}
131
+ }
132
+ )
133
+
134
+ union = []
135
+ remap = {}
136
+ references.each do |obj|
137
+ obj = obj.to_h
138
+ obj[:keyword] = obj.delete("keyword")
139
+ obj[:uri] = obj.delete("uri")
140
+ union, new_remap = BEL::Model.union_namespace_references(union, [obj], 'incr')
141
+ remap.merge!(new_remap)
142
+ end
143
+
144
+ remap
145
+ end
146
+
147
+ def find_all_annotation_references
148
+ references = @collection.aggregate(
149
+ [
150
+ {
151
+ :$project => {"references.annotations" => 1}
152
+ },
153
+ {
154
+ :$unwind => "$references.annotations"
155
+ },
156
+ {
157
+ :$project => {
158
+ keyword: "$references.annotations.keyword",
159
+ type: "$references.annotations.type",
160
+ domain: "$references.annotations.domain"
161
+ }
162
+ },
163
+ {
164
+ :$group => {
165
+ _id: "$keyword",
166
+ type: {
167
+ :$addToSet => "$type"
168
+ },
169
+ domain: {
170
+ :$addToSet => "$domain"
171
+ }
172
+ }
173
+ },
174
+ {
175
+ :$unwind => "$type"
176
+ },
177
+ {
178
+ :$unwind => "$domain"
179
+ },
180
+ {
181
+ :$project => {
182
+ keyword: "$_id", type: "$type", domain: "$domain", _id: 0
183
+ }
184
+ }
185
+ ],
186
+ {
187
+ allowDiskUse: true,
188
+ cursor: {}
189
+ }
190
+ )
191
+
192
+ union = []
193
+ remap = {}
194
+ references.each do |obj|
195
+ obj = obj.to_h
196
+ obj[:keyword] = obj.delete("keyword")
197
+ obj[:type] = obj.delete("type")
198
+ obj[:domain] = obj.delete("domain")
199
+ union, new_remap = BEL::Model.union_annotation_references(union, [obj], 'incr')
200
+ remap.merge!(new_remap)
201
+ end
202
+
203
+ remap
204
+ end
205
+
107
206
  def count_evidence(filters = [])
108
207
  query_hash = to_query(filters)
109
208
  @collection.count(:query => query_hash)
@@ -123,16 +222,16 @@ module OpenBEL
123
222
  nil
124
223
  end
125
224
 
126
- def delete_dataset(identifier)
127
- @collection.ensure_index(
128
- {:"_dataset" => Mongo::ASCENDING },
129
- :background => true
130
- )
225
+ def delete_facets
226
+ @evidence_facets.delete_all_facets
227
+ end
131
228
 
229
+ def delete_dataset(identifier)
132
230
  @collection.remove(
133
231
  { :"_dataset" => identifier },
134
232
  :j => true
135
233
  )
234
+ @evidence_facets.delete_all_facets
136
235
  end
137
236
 
138
237
  def delete_evidence(value)
@@ -173,8 +272,170 @@ module OpenBEL
173
272
  )
174
273
  end
175
274
 
275
+ def ensure_all_indexes
276
+ @collection.ensure_index(
277
+ { :bel_statement => Mongo::ASCENDING },
278
+ :background => true
279
+ )
280
+ @collection.ensure_index(
281
+ { :"$**" => Mongo::TEXT },
282
+ :background => true
283
+ )
284
+ @collection.ensure_index(
285
+ { :_dataset => Mongo::ASCENDING },
286
+ :background => true
287
+ )
288
+ @collection.ensure_index(
289
+ { :"experiment_context.name" => Mongo::ASCENDING },
290
+ :background => true
291
+ )
292
+ @collection.ensure_index(
293
+ { :"metadata.name" => Mongo::ASCENDING },
294
+ :background => true
295
+ )
296
+ end
297
+
176
298
  private
177
299
 
300
+ def evidence_query(filters = [], offset = 0, length = 0, facet = false, facet_value_limit = -1)
301
+ query_hash = to_query(filters)
302
+ query_opts = query_options(
303
+ query_hash,
304
+ :skip => offset,
305
+ :limit => length,
306
+ :sort => [
307
+ [:bel_statement, :asc]
308
+ ]
309
+ )
310
+
311
+ results = {
312
+ :cursor => @collection.find(query_hash, query_opts)
313
+ }
314
+ if facet
315
+ facets_cursor = @evidence_facets.find_facets(query_hash, filters, facet_value_limit)
316
+ results[:facets] = facets_cursor.to_a
317
+ end
318
+
319
+ results
320
+ end
321
+
322
+ def evidence_aggregate(text_search, filters = [], offset = 0, length = 0, facet = false, facet_value_limit = -1)
323
+ match_filters = filters.select { |filter|
324
+ filter['category'] != 'fts'
325
+ }
326
+ match = build_filter_query(match_filters)
327
+ match[:$and].unshift({
328
+ :$text => {
329
+ :$search => text_search
330
+ }
331
+ })
332
+
333
+ pipeline = [
334
+ {
335
+ :$match => match
336
+ },
337
+ {
338
+ :$project => {
339
+ :_id => 1,
340
+ :bel_statement => 1,
341
+ :score => {
342
+ :$meta => 'textScore'
343
+ }
344
+ }
345
+ },
346
+ {
347
+ :$sort => {
348
+ :score => {
349
+ :$meta => 'textScore'
350
+ },
351
+ :bel_statement => 1
352
+ }
353
+ }
354
+ ]
355
+
356
+ if offset > 0
357
+ pipeline << {
358
+ :$skip => offset
359
+ }
360
+ end
361
+
362
+ if length > 0
363
+ pipeline << {
364
+ :$limit => length
365
+ }
366
+ end
367
+
368
+ fts_cursor = @collection.aggregate(pipeline, {
369
+ :allowDiskUse => true,
370
+ :cursor => {
371
+ :batchSize => 0
372
+ }
373
+ })
374
+ _ids = fts_cursor.map { |doc| doc['_id'] }
375
+
376
+ facets =
377
+ if facet
378
+ query_hash = to_query(filters)
379
+ facets_cursor = @evidence_facets.find_facets(query_hash, filters, facet_value_limit)
380
+ facets_cursor.to_a
381
+ else
382
+ nil
383
+ end
384
+
385
+ {
386
+ :cursor => @collection.find({:_id => {:$in => _ids}}),
387
+ :facets => facets
388
+ }
389
+ end
390
+
391
+ def includes_fts_search?(filters)
392
+ filters.any? { |filter|
393
+ filter['category'] == 'fts' && filter['name'] == 'search'
394
+ }
395
+ end
396
+
397
+ def get_fts_search(filters)
398
+ fts_filter = filters.find { |filter|
399
+ filter['category'] == 'fts' && filter['name'] == 'search'
400
+ }
401
+ fts_filter.fetch('value', '')
402
+ end
403
+
404
+ def build_filter_query(filters = [])
405
+ {
406
+ :$and => filters.map { |filter|
407
+ category = filter['category']
408
+ name = filter['name']
409
+ value = filter['value']
410
+
411
+ case category
412
+ when 'experiment_context'
413
+ {
414
+ :experiment_context => {
415
+ :$elemMatch => {
416
+ :name => name.to_s,
417
+ :value => value.to_s
418
+ }
419
+ }
420
+ }
421
+ when 'metadata'
422
+ {
423
+ :metadata => {
424
+ :$elemMatch => {
425
+ :name => name.to_s,
426
+ :value => value.to_s
427
+ }
428
+ }
429
+ }
430
+ else
431
+ {
432
+ "#{filter['category']}.#{filter['name']}" => filter['value'].to_s
433
+ }
434
+ end
435
+ }
436
+ }
437
+ end
438
+
178
439
  def to_query(filters = [])
179
440
  if !filters || filters.empty?
180
441
  return {}
@@ -238,13 +499,12 @@ module OpenBEL
238
499
  end
239
500
 
240
501
  def remove_evidence_facets(_id)
241
- evidence = @collection.find_one(_id, {
242
- :fields => [ 'facets' ]
502
+ doc = @collection.find_one(_id, {
503
+ :fields => {:_id => 0, :facets => 1}
243
504
  })
244
505
 
245
- if evidence && evidence.has_key?('facets')
246
- @evidence_facets.remove_facets_by_filters(evidence['facets'])
247
- @evidence_facets.remove_facets_by_filters
506
+ if doc && doc.has_key?('facets')
507
+ @evidence_facets.delete_facets(doc['facets'])
248
508
  end
249
509
  end
250
510
  end