-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CUMULUS-3641 - Update Collections LIST endpoint to query Postgres basic #3681
Changes from all commits
993d72a
65dfe5e
e4c1e59
d7dd6cf
b557e9e
c89f0f9
f19244c
43b1cd7
f386137
be810af
682660b
cea3c14
1e6d54e
aaec2a2
2ee8efd
ca6b106
0d9f057
d0ae579
b282642
3ca493d
52281e8
db45ecd
9f613ba
bc40d57
6aeb39f
e208d5e
5433023
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//@ts-check | ||
|
||
'use strict'; | ||
|
||
const router = require('express-promise-router')(); | ||
|
@@ -16,6 +18,7 @@ const { | |
isCollisionError, | ||
translateApiCollectionToPostgresCollection, | ||
translatePostgresCollectionToApiCollection, | ||
CollectionSearch, | ||
} = require('@cumulus/db'); | ||
const CollectionConfigStore = require('@cumulus/collection-config-store'); | ||
const { getEsClient, Search } = require('@cumulus/es-client/search'); | ||
|
@@ -43,14 +46,22 @@ const log = new Logger({ sender: '@cumulus/api/collections' }); | |
* @returns {Promise<Object>} the promise of express response object | ||
*/ | ||
async function list(req, res) { | ||
Nnaga1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
log.trace(`list query ${JSON.stringify(req.query)}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: we almost never use trace over .info. A decision to start doing that should be deliberate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Jenny added it to granules during the granule endpoint work: https://github.com/nasa/cumulus/pull/3648/files#diff-624123a7dc5bb5513e3769b27fe85821577087609a9376829676b7edbeb3a5aeR104 so we were trying to be consistent There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, sure, that comment applies to both PRs then - this is in theory a change to how we're logging. We should broadcast (arch meting) and decide to do it, else efforts outside this insular work won't be consistent with the approach you're choosing. It's minor and shouldn't block the PR (nit), but it's notable, particularly if we ever get around to log-level squelching. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will add a comment to the feature branch, so we can revisit when Jenny is back and when we are thinking of merging the feature branch. |
||
const { getMMT, includeStats, ...queryStringParameters } = req.query; | ||
const collection = new Collection( | ||
{ queryStringParameters }, | ||
undefined, | ||
process.env.ES_INDEX, | ||
includeStats === 'true' | ||
); | ||
let result = await collection.query(); | ||
let dbSearch; | ||
if (includeStats === 'true') { | ||
Nnaga1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
dbSearch = new Collection( | ||
{ queryStringParameters }, | ||
undefined, | ||
process.env.ES_INDEX, | ||
includeStats === 'true' | ||
); | ||
} else { | ||
dbSearch = new CollectionSearch( | ||
{ queryStringParameters } | ||
); | ||
} | ||
let result = await dbSearch.query(); | ||
if (getMMT === 'true') { | ||
result = await insertMMTLinks(result); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Knex } from 'knex'; | ||
import pick from 'lodash/pick'; | ||
|
||
import Logger from '@cumulus/logger'; | ||
import { CollectionRecord } from '@cumulus/types/api/collections'; | ||
Nnaga1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import { BaseSearch } from './BaseSearch'; | ||
import { DbQueryParameters, QueryEvent } from '../types/search'; | ||
import { translatePostgresCollectionToApiCollection } from '../translate/collections'; | ||
import { PostgresCollectionRecord } from '../types/collection'; | ||
|
||
const log = new Logger({ sender: '@cumulus/db/CollectionSearch' }); | ||
|
||
/** | ||
* There is no need to declare an ApiCollectionRecord type since | ||
* CollectionRecord contains all the same fields from the api | ||
*/ | ||
|
||
/** | ||
* Class to build and execute db search query for collection | ||
*/ | ||
export class CollectionSearch extends BaseSearch { | ||
constructor(event: QueryEvent) { | ||
super(event, 'collection'); | ||
} | ||
|
||
/** | ||
* Build basic query | ||
* | ||
* @param knex - DB client | ||
* @returns queries for getting count and search result | ||
*/ | ||
protected buildBasicQuery(knex: Knex) | ||
: { | ||
countQuery: Knex.QueryBuilder, | ||
searchQuery: Knex.QueryBuilder, | ||
} { | ||
const countQuery = knex(this.tableName) | ||
.count(`${this.tableName}.cumulus_id`); | ||
|
||
const searchQuery = knex(this.tableName) | ||
.select(`${this.tableName}.*`); | ||
return { countQuery, searchQuery }; | ||
} | ||
|
||
/** | ||
* Build queries for infix and prefix | ||
* | ||
* @param params | ||
* @param params.countQuery - query builder for getting count | ||
* @param params.searchQuery - query builder for search | ||
* @param [params.dbQueryParameters] - db query parameters | ||
*/ | ||
protected buildInfixPrefixQuery(params: { | ||
countQuery: Knex.QueryBuilder, | ||
searchQuery: Knex.QueryBuilder, | ||
dbQueryParameters?: DbQueryParameters, | ||
}) { | ||
const { countQuery, searchQuery, dbQueryParameters } = params; | ||
const { infix, prefix } = dbQueryParameters ?? this.dbQueryParameters; | ||
if (infix) { | ||
[countQuery, searchQuery].forEach((query) => query.whereLike(`${this.tableName}.name`, `%${infix}%`)); | ||
} | ||
if (prefix) { | ||
[countQuery, searchQuery].forEach((query) => query.whereLike(`${this.tableName}.name`, `%${prefix}%`)); | ||
} | ||
} | ||
|
||
/** | ||
* Translate postgres records to api records | ||
* | ||
* @param pgRecords - postgres records returned from query | ||
* @returns translated api records | ||
*/ | ||
protected translatePostgresRecordsToApiRecords(pgRecords: PostgresCollectionRecord[]) | ||
: Partial<CollectionRecord>[] { | ||
log.debug(`translatePostgresRecordsToApiRecords number of records ${pgRecords.length} `); | ||
const apiRecords = pgRecords.map((item) => { | ||
const apiRecord = translatePostgresCollectionToApiCollection(item); | ||
|
||
return this.dbQueryParameters.fields | ||
? pick(apiRecord, this.dbQueryParameters.fields) | ||
: apiRecord; | ||
}); | ||
return apiRecords; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,6 +123,18 @@ const collectionMapping : { [key: string]: Function } = { | |
updatedAt: (value?: string) => ({ | ||
updated_at: value && new Date(Number(value)), | ||
}), | ||
reportToEms: (value?: string) => ({ | ||
charleshuang80 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, keep forgetting to add this comment. The feature branch has a test file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not each time, I think based on how Jenny made that file/test, as long as that test-field-mapping test passes, and the correct response/correct format is returned, it should be fine. the reason to add field-mappings in the first place is so term search can work for the specific table, and we test the term search in the respective Search tests There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I missed the actual test before, but it is in that file I referenced on line 104. I think that test should include some of these fields you added, like report_to_ems, sample_file_name, and url_path |
||
report_to_ems: (value === 'true'), | ||
}), | ||
process: (value?: string) => ({ | ||
process: value, | ||
}), | ||
sampleFileName: (value?: string) => ({ | ||
sample_file_name: value, | ||
}), | ||
urlPath: (value?: string) => ({ | ||
url_path: value, | ||
}), | ||
}; | ||
|
||
const executionMapping : { [key: string]: Function } = { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add support for
_id__in
for collection db query.