mirror of
https://gitlab.com/wheres-the-tp/server.git
synced 2026-01-25 06:14:55 -06:00
separate images into its own table
This commit is contained in:
parent
1a0bfbe6a6
commit
8da28e8406
5 changed files with 108 additions and 65 deletions
|
|
@ -1,106 +1,100 @@
|
|||
CREATE EXTENSION IF NOT EXISTS "postgis";
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
DROP TYPE IF EXISTS QUANTITY CASCADE;
|
||||
CREATE TYPE QUANTITY AS ENUM ('lots', 'many', 'few', 'none');
|
||||
DROP TYPE IF EXISTS CATEGORY CASCADE;
|
||||
CREATE TYPE CATEGORY AS ENUM ('beverages', 'desserts', 'entrees', 'other');
|
||||
DROP TABLE IF EXISTS food_items CASCADE;
|
||||
CREATE TABLE food_items (
|
||||
id uuid PRIMARY KEY,
|
||||
name VARCHAR(100),
|
||||
place_id VARCHAR(50),
|
||||
category CATEGORY,
|
||||
images VARCHAR,
|
||||
thumbImage VARCHAR,
|
||||
loc geography(POINT,4326)
|
||||
id uuid PRIMARY KEY,
|
||||
name VARCHAR(100),
|
||||
place_id VARCHAR(50),
|
||||
category CATEGORY,
|
||||
images VARCHAR,
|
||||
thumbImage VARCHAR,
|
||||
loc geography(POINT,4326)
|
||||
);
|
||||
DROP TABLE quantities CASCADE;
|
||||
DROP TABLE IF EXISTS images CASCADE;
|
||||
CREATE TABLE images (
|
||||
filename VARCHAR(200) PRIMARY KEY,
|
||||
food_item_id uuid REFERENCES food_items (id),
|
||||
username VARCHAR(100),
|
||||
date timestamp (1) with time zone
|
||||
);
|
||||
DROP TABLE IF EXISTS quantities CASCADE;
|
||||
CREATE TABLE quantities (
|
||||
food_item_id uuid,
|
||||
food_item_id uuid REFERENCES food_items (id),
|
||||
date timestamp (1) with time zone,
|
||||
quantity QUANTITY,
|
||||
PRIMARY KEY(food_item_id, date)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS food_loc_index ON food_items USING GIST ( loc );
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
DROP VIEW IF EXISTS latest_quantities;
|
||||
CREATE VIEW latest_quantities AS SELECT food_item_id, quantity, date from quantities q1 where date = (
|
||||
SELECT max(date) FROM quantities q2 WHERE q1.food_item_id=q2.food_item_id
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Big John Cookies',
|
||||
'ChIJf5QJFBK1RIYRjjfxZz9Z0O0',
|
||||
'desserts',
|
||||
'https://s-media-cache-ak0.pinimg.com/564x/e7/5f/08/e75f08b00c0bc7f2b01b3d1a636389f6.jpg,http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
|
||||
'http://images.media-allrecipes.com/userphotos/560x315/1107530.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.7532464 30.270667599999996)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Jelly Filled Donuts',
|
||||
'ChIJ72if-Qe1RIYRCzMucGEEdBA',
|
||||
'desserts',
|
||||
'https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg',
|
||||
'https://timenewsfeed.files.wordpress.com/2013/06/jellydonut.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Spelt Brownies',
|
||||
'ChIJG44vBQi1RIYRvWGHdYUolZY',
|
||||
'desserts',
|
||||
'http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg',
|
||||
'http://www.momshealthyeats.com/wp-content/uploads/2011/11/spelt-fudge-brownie.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.7419085 30.265019100000004)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Oatmeal Raisin Cookies',
|
||||
'ChIJf5QJFBK1RIYRjjfxZz9Z0O0',
|
||||
'desserts',
|
||||
'http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg',
|
||||
'http://cookingontheside.com/wp-content/uploads/2009/04/oatmeal_raisin_cookies_stack-400.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.7532464 30.270667599999996)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Donuts with Sprinkles',
|
||||
'ChIJ72if-Qe1RIYRCzMucGEEdBA',
|
||||
'desserts',
|
||||
'https://dannivee.files.wordpress.com/2013/10/img_1950.jpg',
|
||||
'https://dannivee.files.wordpress.com/2013/10/img_1950.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Powdered Donuts',
|
||||
'ChIJ72if-Qe1RIYRCzMucGEEdBA',
|
||||
'desserts',
|
||||
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
|
||||
'http://3.bp.blogspot.com/-NUKSXr1qLHs/UQmsaEFgbTI/AAAAAAAAA_Y/l4psfVl4a5A/s1600/white-powdered-sugar-doughnuts-tracie-kaska.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.742308 30.263963300000004)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Snickerdoodles',
|
||||
'ChIJr3szW6a1RIYRkM7LRpnBIO0',
|
||||
'desserts',
|
||||
'http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg',
|
||||
'http://josephcphillips.com/wp-content/uploads/2015/02/snickerdoodles2.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.73798459999999 30.266898599999998)')
|
||||
);
|
||||
INSERT INTO food_items (id, name, place_id, category, images, thumbImage, loc)
|
||||
INSERT INTO food_items (id, name, place_id, category, loc)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'Pizza',
|
||||
'ChIJr3szW6a1RIYRkM7LRpnBIO0',
|
||||
'desserts',
|
||||
'http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg',
|
||||
'http://www.foodandhealth.co.uk/wp-content/uploads/2016/05/Hot-stone-Vegan-Pizza.jpg',
|
||||
ST_GeogFromText('SRID=4326;POINT(-97.73798459999999 30.266898599999998)')
|
||||
);
|
||||
INSERT INTO quantities SELECT id, current_timestamp, 'many' FROM food_items;
|
||||
CREATE VIEW latest_quantities AS SELECT food_item_id, quantity, date from quantities q1 where date = (
|
||||
SELECT max(date) FROM quantities q2 WHERE q1.food_item_id=q2.food_item_id
|
||||
);
|
||||
|
|
@ -5,7 +5,13 @@
|
|||
|
||||
(defcredential (env :aws-access-key-id) (env :aws-secret-access-key) (env :aws-region))
|
||||
|
||||
|
||||
(defn put-s3
|
||||
"upload given filename and file to s3"
|
||||
[file-name file]
|
||||
(put-object :bucket-name "aretherecookies" :key file-name :file file))
|
||||
|
||||
(defn build-s3-url
|
||||
"given an image name return fully qualified URL"
|
||||
[filename]
|
||||
(str "https://s3-us-west-2.amazonaws.com/aretherecookies/" filename))
|
||||
|
|
|
|||
|
|
@ -84,10 +84,9 @@
|
|||
(defn get-images
|
||||
"query database for a list of images for a food item id"
|
||||
[foodItemId]
|
||||
(let [images (:images (select-images @pooled-db {:id foodItemId}))]
|
||||
(filter #(not (str/blank? %)) (str/split (str images) #","))))
|
||||
(select-images @pooled-db {:id foodItemId}))
|
||||
|
||||
(defn set-images
|
||||
(defn add-image
|
||||
"update the list of images for given food item id"
|
||||
[foodItemId images]
|
||||
(update-images @pooled-db {:id foodItemId :images (str/join "," images)}))
|
||||
[image]
|
||||
(insert-image @pooled-db image))
|
||||
|
|
@ -3,32 +3,61 @@
|
|||
insert-quantity
|
||||
create-food-item
|
||||
get-images
|
||||
set-images]]
|
||||
[aretherecookies.parsers :refer [parse-special-types parse-location]]
|
||||
[aretherecookies.aws :refer [put-s3]]
|
||||
add-image]]
|
||||
[aretherecookies.parsers :refer [parse-special-types
|
||||
parse-location]]
|
||||
[aretherecookies.aws :refer [put-s3
|
||||
build-s3-url]]
|
||||
[clojure.data.json :as json]
|
||||
[clojure.string :as str]
|
||||
[buddy.auth :refer [authenticated? throw-unauthorized]]))
|
||||
[buddy.auth :refer [authenticated?
|
||||
throw-unauthorized]])
|
||||
(:import (java.util UUID)))
|
||||
|
||||
|
||||
(defn safe-json
|
||||
"converts hashmaps into a JSON string suitable for a network response"
|
||||
[data]
|
||||
(json/write-str data :value-fn parse-special-types))
|
||||
|
||||
|
||||
(defn bad-request
|
||||
"returns a HTTP 404 error with the supplied body"
|
||||
[body]
|
||||
{:status 400 :body (safe-json body)})
|
||||
|
||||
(defn food-items-handler [req]
|
||||
|
||||
(defn image-filename-to-url
|
||||
"convert image filename key to url key"
|
||||
[image]
|
||||
(assoc image :url (build-s3-url (get image :filename))))
|
||||
|
||||
|
||||
(defn images-to-s3-urls
|
||||
"convert all the images of a food item to fully qualified s3 URLs"
|
||||
[food-item]
|
||||
(if (get :images food-item)
|
||||
(update food-item :images (map build-s3-url))
|
||||
food-item))
|
||||
|
||||
|
||||
(defn food-items-handler
|
||||
"return a list of food items for a given filter and location"
|
||||
[req]
|
||||
(println "/fooditems ---->" (:body req))
|
||||
(let [{body :body} req]
|
||||
(safe-json
|
||||
(hash-map
|
||||
:filter (:filter body)
|
||||
:fooditems (map parse-location (query-food-items body))))))
|
||||
:fooditems (->>
|
||||
(query-food-items body)
|
||||
(map parse-location)
|
||||
(map images-to-s3-urls))))))
|
||||
|
||||
(defn quantity-handler [req]
|
||||
|
||||
(defn quantity-handler
|
||||
"get the latest quantity for a food item"
|
||||
[req]
|
||||
(let [{{foodItemId :foodItemId quantity :quantity} :body} req]
|
||||
(if-not (authenticated? req) (throw-unauthorized))
|
||||
(println "/quantity ---->" foodItemId quantity)
|
||||
|
|
@ -36,10 +65,14 @@
|
|||
(insert-quantity {:foodItemId foodItemId :quantity quantity})
|
||||
:value-fn parse-special-types)))
|
||||
|
||||
(def required-keys [:name :placeId :latitude :longitude :category :quantity])
|
||||
|
||||
(defn get-missing-keys
|
||||
"returns a list of required keys which were not found on the given food item"
|
||||
[foodItem]
|
||||
(remove #(get foodItem %) required-keys))
|
||||
(remove
|
||||
#(get foodItem %)
|
||||
[:name :placeId :latitude :longitude :category :quantity]))
|
||||
|
||||
|
||||
(defn add-food-item-handler
|
||||
"validate food item fields from request and insert into database returning newly created item"
|
||||
|
|
@ -54,13 +87,18 @@
|
|||
(parse-location %)
|
||||
(safe-json %)))))
|
||||
|
||||
|
||||
(defn add-image-handler
|
||||
"given foodItemId from route and photo from multipart form post uploads image into s3 and adds URL into food item record"
|
||||
[{{foodItemId :foodItemId {image :tempfile} :photo} :params}]
|
||||
(let [existing-images (get-images foodItemId)
|
||||
img-name (str foodItemId "/" (+ 1 (count existing-images)) ".png")
|
||||
img-url (str "https://s3-us-west-2.amazonaws.com/aretherecookies/" img-name)]
|
||||
(println "/addimage ---->" img-url)
|
||||
[req]
|
||||
(if-not (authenticated? req) (throw-unauthorized))
|
||||
(let [username (get-in req [:params :username] "Bart Akeley")
|
||||
foodItemId (get-in req [:params :foodItemId])
|
||||
image (get-in req [:params :photo :tempfile])
|
||||
img-name (str foodItemId "/" (UUID/randomUUID) ".png")]
|
||||
(println "/addimage ---->" img-name)
|
||||
(put-s3 img-name image)
|
||||
(set-images foodItemId (conj existing-images img-url))
|
||||
img-url))
|
||||
(add-image {:food_item_id foodItemId
|
||||
:filename img-name
|
||||
:username username})
|
||||
(build-s3-url img-name)))
|
||||
|
|
@ -4,12 +4,12 @@ SELECT
|
|||
f.name AS name,
|
||||
f.place_id AS place_id,
|
||||
f.category AS category,
|
||||
f.images AS images,
|
||||
f.thumbImage AS thumbImage,
|
||||
ST_AsGeoJSON(f.loc) AS location,
|
||||
ST_Distance(f.loc, ST_SetSRID(ST_Point(:lng, :lat), 4326)::geography) / 1609 AS distance,
|
||||
q.quantity AS quantity,
|
||||
q.date AS lastUpdated
|
||||
q.date AS lastUpdated,
|
||||
(select filename from images where food_item_id = f.id) as images
|
||||
FROM food_items f
|
||||
LEFT OUTER JOIN latest_quantities q
|
||||
ON f.id = q.food_item_id
|
||||
|
|
@ -59,13 +59,19 @@ RETURNING
|
|||
name AS name,
|
||||
place_id AS place_id,
|
||||
category AS category,
|
||||
images AS images,
|
||||
thumbImage AS thumbImage,
|
||||
ST_AsGeoJSON(loc) AS location,
|
||||
ST_Distance(loc, ST_SetSRID(ST_Point(:longitude, :latitude), 4326)::geography) / 1609 AS distance
|
||||
|
||||
-- :name select-images
|
||||
SELECT images FROM food_items WHERE id=:v:id::uuid
|
||||
SELECT * FROM images WHERE food_item-id=:v:food_item_id:uuid
|
||||
|
||||
-- :name update-images
|
||||
UPDATE food_items SET images=:v:images WHERE id=:v:id::uuid RETURNING images
|
||||
-- :name insert-image
|
||||
INSERT INTO images (filename, username, date, food_item_id)
|
||||
VALUES (
|
||||
:v:filename,
|
||||
:v:username,
|
||||
current_timestamp,
|
||||
:v:food_item_id::uuid
|
||||
)
|
||||
RETURNING *
|
||||
Loading…
Add table
Reference in a new issue