separate images into its own table

This commit is contained in:
Bart Akeley 2018-03-10 11:56:40 -06:00
parent 1a0bfbe6a6
commit 8da28e8406
5 changed files with 108 additions and 65 deletions

View file

@ -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
);

View file

@ -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))

View file

@ -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))

View file

@ -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)))

View file

@ -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 *