(ns metabase.indexed-entities.api (:require [metabase.analytics.core :as analytics] [metabase.api.common :as api] [metabase.api.macros :as api.macros] [metabase.indexed-entities.models.model-index :as model-index] [metabase.indexed-entities.task.index-values :as task.index-values] [metabase.legacy-mbql.normalize :as mbql.normalize] [metabase.util.i18n :refer [tru]] [metabase.util.malli.schema :as ms] [toucan2.core :as t2])) | |
Ensure that the ref exists and is of type required for indexing. | (defn- ensure-type
[t ref metadata]
(if-let [field (some (fn [f] (when ((comp #{(mbql.normalize/normalize-field-ref ref)} :field_ref) f)
f))
metadata)]
(let [type-slot (case t
:type/PK :semantic_type
(:type/Integer :type/Text) :effective_type)]
(when-not (isa? (type-slot field) t)
(throw (ex-info (tru "Field is not of {0} `{1}`" type-slot t)
{:status-code 400
:expected-type t
:type (:effective_type field)
:field (:name field)}))))
(throw (ex-info (tru "Could not identify field by ref {0}" ref)
{:status-code 400
:ref ref
:fields metadata})))) |
(api.macros/defendpoint :post "/"
"Create ModelIndex."
[_route-params
_query-params
{:keys [model_id pk_ref value_ref] :as _model-index} :- [:map
[:model_id ms/PositiveInt]
[:pk_ref any?]
[:value_ref any?]]]
(let [model (api/write-check :model/Card model_id)
metadata (:result_metadata model)]
(when-not (seq metadata)
(throw (ex-info (tru "Model has no metadata. Cannot index")
{:model-id model_id})))
(ensure-type :type/PK pk_ref metadata)
(ensure-type :type/Integer pk_ref metadata)
(ensure-type :type/Text value_ref metadata)
;; todo: do we care if there's already an index on that model?
(let [model-index (model-index/create {:model-id model_id
:pk-ref pk_ref
:value-ref value_ref
:creator-id api/*current-user-id*})]
(analytics/track-event! :snowplow/model
{:event :index-model-entities-enabled
:model-id model_id})
(task.index-values/add-indexing-job model-index)
(model-index/add-values! model-index)
(t2/select-one :model/ModelIndex :id (:id model-index))))) | |
(api.macros/defendpoint :get "/"
"Retrieve list of ModelIndex."
[_route-params
{:keys [model_id]} :- [:map
[:model_id ms/PositiveInt]]]
(let [model (api/read-check :model/Card model_id)]
(when-not (= (:type model) :model)
(throw (ex-info (tru "Question {0} is not a model" model_id)
{:model_id model_id
:status-code 400})))
(t2/select :model/ModelIndex :model_id model_id))) | |
(api.macros/defendpoint :get "/:id"
"Retrieve ModelIndex."
[{:keys [id]} :- [:map
[:id ms/PositiveInt]]]
(let [model-index (api/check-404 (t2/select-one :model/ModelIndex :id id))
model (api/read-check :model/Card (:model_id model-index))]
(when-not (= (:type model) :model)
(throw (ex-info (tru "Question {0} is not a model" id)
{:model_id id
:status-code 400})))
model-index)) | |
(api.macros/defendpoint :delete "/:id"
"Delete ModelIndex."
[{:keys [id]} :- [:map
[:id ms/PositiveInt]]]
(api/let-404 [model-index (t2/select-one :model/ModelIndex :id id)]
(api/write-check :model/Card (:model_id model-index))
(t2/delete! :model/ModelIndex id))) | |