Beef up strains payload
This commit is contained in:
parent
86e6c45a2f
commit
12b460db9a
2 changed files with 115 additions and 16 deletions
|
@ -277,9 +277,10 @@ func listCharacteristics(opt ListOptions, claims *Claims) (*Characteristics, err
|
||||||
q += fmt.Sprintf(" WHERE %s", w)
|
q += fmt.Sprintf(" WHERE %s", w)
|
||||||
}
|
}
|
||||||
|
|
||||||
q += " GROUP BY c.id, ct.characteristic_type_name;"
|
q += ` GROUP BY c.id, ct.characteristic_type_name
|
||||||
|
ORDER BY ct.characteristic_type_name, c.sort_order ASC;`
|
||||||
|
|
||||||
characteristics := make(Characteristics, 0)
|
var characteristics Characteristics
|
||||||
err := DBH.Select(&characteristics, q, vals...)
|
err := DBH.Select(&characteristics, q, vals...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
126
strains.go
126
strains.go
|
@ -56,6 +56,7 @@ type StrainBase struct {
|
||||||
type Strain struct {
|
type Strain struct {
|
||||||
*StrainBase
|
*StrainBase
|
||||||
Measurements NullSliceInt64 `db:"measurements" json:"measurements"`
|
Measurements NullSliceInt64 `db:"measurements" json:"measurements"`
|
||||||
|
Characteristics NullSliceInt64 `db:"characteristics" json:"characteristics"`
|
||||||
TotalMeasurements int64 `db:"total_measurements" json:"totalMeasurements"`
|
TotalMeasurements int64 `db:"total_measurements" json:"totalMeasurements"`
|
||||||
SortOrder int64 `db:"sort_order" json:"sortOrder"`
|
SortOrder int64 `db:"sort_order" json:"sortOrder"`
|
||||||
CanEdit bool `db:"-" json:"canEdit"`
|
CanEdit bool `db:"-" json:"canEdit"`
|
||||||
|
@ -68,15 +69,19 @@ type StrainMeta struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type StrainPayload struct {
|
type StrainPayload struct {
|
||||||
Strain *Strain `json:"strain"`
|
Strain *Strain `json:"strain"`
|
||||||
Species *ManySpecies `json:"species"`
|
Species *ManySpecies `json:"species"`
|
||||||
Meta *StrainMeta `json:"meta"`
|
Characteristics *Characteristics `json:"characteristics"`
|
||||||
|
Measurements *Measurements `json:"measurements"`
|
||||||
|
Meta *StrainMeta `json:"meta"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type StrainsPayload struct {
|
type StrainsPayload struct {
|
||||||
Strains *Strains `json:"strains"`
|
Strains *Strains `json:"strains"`
|
||||||
Species *ManySpecies `json:"species"`
|
Species *ManySpecies `json:"species"`
|
||||||
Meta *StrainMeta `json:"meta"`
|
Characteristics *Characteristics `json:"characteristics"`
|
||||||
|
Measurements *Measurements `json:"measurements"`
|
||||||
|
Meta *StrainMeta `json:"meta"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StrainPayload) marshal() ([]byte, error) {
|
func (s *StrainPayload) marshal() ([]byte, error) {
|
||||||
|
@ -125,9 +130,44 @@ func (s StrainService) list(val *url.Values, claims *Claims) (entity, *appError)
|
||||||
return nil, newJSONError(err, http.StatusInternalServerError)
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
characteristics_opt, err := characteristicsOptsFromStrains(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristics, err := listCharacteristics(*characteristics_opt, claims)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristic_ids := []int64{}
|
||||||
|
for _, c := range *characteristics {
|
||||||
|
characteristic_ids = append(characteristic_ids, c.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
strain_ids := []int64{}
|
||||||
|
for _, s := range *strains {
|
||||||
|
strain_ids = append(strain_ids, s.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
measurement_opt := MeasurementListOptions{
|
||||||
|
ListOptions: ListOptions{
|
||||||
|
Genus: opt.Genus,
|
||||||
|
},
|
||||||
|
Strains: strain_ids,
|
||||||
|
Characteristics: characteristic_ids,
|
||||||
|
}
|
||||||
|
|
||||||
|
measurements, err := listMeasurements(measurement_opt, claims)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
payload := StrainsPayload{
|
payload := StrainsPayload{
|
||||||
Strains: strains,
|
Strains: strains,
|
||||||
Species: species,
|
Species: species,
|
||||||
|
Measurements: measurements,
|
||||||
|
Characteristics: characteristics,
|
||||||
Meta: &StrainMeta{
|
Meta: &StrainMeta{
|
||||||
CanAdd: canAdd(claims),
|
CanAdd: canAdd(claims),
|
||||||
},
|
},
|
||||||
|
@ -147,11 +187,42 @@ func (s StrainService) get(id int64, genus string, claims *Claims) (entity, *app
|
||||||
return nil, newJSONError(err, http.StatusInternalServerError)
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opt := ListOptions{Genus: genus, Ids: []int64{id}}
|
||||||
|
characteristics_opt, err := characteristicsOptsFromStrains(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristics, err := listCharacteristics(*characteristics_opt, claims)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristic_ids := []int64{}
|
||||||
|
for _, c := range *characteristics {
|
||||||
|
characteristic_ids = append(characteristic_ids, c.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
measurement_opt := MeasurementListOptions{
|
||||||
|
ListOptions: ListOptions{
|
||||||
|
Genus: genus,
|
||||||
|
},
|
||||||
|
Strains: []int64{id},
|
||||||
|
Characteristics: characteristic_ids,
|
||||||
|
}
|
||||||
|
|
||||||
|
measurements, err := listMeasurements(measurement_opt, claims)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
var many_species ManySpecies = []*Species{species}
|
var many_species ManySpecies = []*Species{species}
|
||||||
|
|
||||||
payload := StrainPayload{
|
payload := StrainPayload{
|
||||||
Strain: strain,
|
Strain: strain,
|
||||||
Species: &many_species,
|
Species: &many_species,
|
||||||
|
Characteristics: characteristics,
|
||||||
|
Measurements: measurements,
|
||||||
Meta: &StrainMeta{
|
Meta: &StrainMeta{
|
||||||
CanAdd: canAdd(claims),
|
CanAdd: canAdd(claims),
|
||||||
},
|
},
|
||||||
|
@ -227,7 +298,9 @@ func (s StrainService) create(e *entity, genus string, claims *Claims) *appError
|
||||||
func listStrains(opt ListOptions, claims *Claims) (*Strains, error) {
|
func listStrains(opt ListOptions, claims *Claims) (*Strains, error) {
|
||||||
var vals []interface{}
|
var vals []interface{}
|
||||||
|
|
||||||
q := `SELECT st.*, array_agg(m.id) AS measurements, COUNT(m) AS total_measurements,
|
q := `SELECT st.*, array_agg(m.id) AS measurements,
|
||||||
|
array_agg(DISTINCT m.characteristic_id) AS characteristics,
|
||||||
|
COUNT(m) AS total_measurements,
|
||||||
rank() OVER (ORDER BY sp.species_name ASC, st.type_strain ASC, st.strain_name ASC) AS sort_order
|
rank() OVER (ORDER BY sp.species_name ASC, st.type_strain ASC, st.strain_name ASC) AS sort_order
|
||||||
FROM strains st
|
FROM strains st
|
||||||
INNER JOIN species sp ON sp.id=st.species_id
|
INNER JOIN species sp ON sp.id=st.species_id
|
||||||
|
@ -264,14 +337,15 @@ func listStrains(opt ListOptions, claims *Claims) (*Strains, error) {
|
||||||
|
|
||||||
func getStrain(id int64, genus string, claims *Claims) (*Strain, error) {
|
func getStrain(id int64, genus string, claims *Claims) (*Strain, error) {
|
||||||
var strain Strain
|
var strain Strain
|
||||||
q := `SELECT st.*, array_agg(m.id) AS measurements,
|
q := `SELECT st.*, array_agg(DISTINCT m.id) AS measurements,
|
||||||
|
array_agg(DISTINCT m.characteristic_id) AS characteristics,
|
||||||
COUNT(m) AS total_measurements, 0 AS sort_order
|
COUNT(m) AS total_measurements, 0 AS sort_order
|
||||||
FROM strains st
|
FROM strains st
|
||||||
INNER JOIN species sp ON sp.id=st.species_id
|
INNER JOIN species sp ON sp.id=st.species_id
|
||||||
INNER JOIN genera g ON g.id=sp.genus_id AND LOWER(g.genus_name)=LOWER($1)
|
INNER JOIN genera g ON g.id=sp.genus_id AND LOWER(g.genus_name)=LOWER($1)
|
||||||
LEFT OUTER JOIN measurements m ON m.strain_id=st.id
|
INNER JOIN measurements m ON m.strain_id=st.id
|
||||||
WHERE st.id=$2
|
WHERE st.id=$2
|
||||||
GROUP BY st.id, st.species_id;`
|
GROUP BY st.id;`
|
||||||
if err := DBH.SelectOne(&strain, q, genus, id); err != nil {
|
if err := DBH.SelectOne(&strain, q, genus, id); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, ErrStrainNotFound
|
return nil, ErrStrainNotFound
|
||||||
|
@ -306,3 +380,27 @@ func speciesOptsFromStrains(opt ListOptions) (*ListOptions, error) {
|
||||||
|
|
||||||
return &ListOptions{Genus: opt.Genus, Ids: relatedSpeciesIds}, nil
|
return &ListOptions{Genus: opt.Genus, Ids: relatedSpeciesIds}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func characteristicsOptsFromStrains(opt ListOptions) (*ListOptions, error) {
|
||||||
|
relatedCharacteristicsIds := make([]int64, 0)
|
||||||
|
|
||||||
|
if opt.Ids == nil || len(opt.Ids) == 0 {
|
||||||
|
q := `SELECT DISTINCT m.characteristic_id
|
||||||
|
FROM measurements m
|
||||||
|
INNER JOIN strains st ON st.id=m.strain_id
|
||||||
|
INNER JOIN species sp ON sp.id=st.species_id
|
||||||
|
INNER JOIN genera g ON g.id=sp.genus_id AND LOWER(g.genus_name)=LOWER($1);`
|
||||||
|
if err := DBH.Select(&relatedCharacteristicsIds, q, opt.Genus); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var vals []interface{}
|
||||||
|
var count int64 = 1
|
||||||
|
q := fmt.Sprintf("SELECT DISTINCT characteristic_id FROM measurements WHERE %s;", valsIn("strain_id", opt.Ids, &vals, &count))
|
||||||
|
if err := DBH.Select(&relatedCharacteristicsIds, q, vals...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ListOptions{Genus: opt.Genus, Ids: relatedCharacteristicsIds}, nil
|
||||||
|
}
|
||||||
|
|
Reference in a new issue