diff --git a/dev/src/dev.clj b/dev/src/dev.clj
index 97f2d7dd6490814324eed78ea7e99868f33ca874..12db644614c447cdd7579db0c0191765a033ec5f 100644
--- a/dev/src/dev.clj
+++ b/dev/src/dev.clj
@@ -39,6 +39,7 @@
    [clojure.string :as str]
    [dev.debug-qp :as debug-qp]
    [dev.model-tracking :as model-tracking]
+   [dev.explain :as dev.explain]
    [honeysql.core :as hsql]
    [malli.dev :as malli-dev]
    [metabase.api.common :as api]
@@ -79,6 +80,8 @@
  [debug-qp
   process-query-debug
   pprint-sql]
+ [dev.explain
+  explain-query]
  [model-tracking
   track!
   untrack!
diff --git a/dev/src/dev/explain.clj b/dev/src/dev/explain.clj
new file mode 100644
index 0000000000000000000000000000000000000000..b66668f5b2c410e90f0125ec0434c500c4662c63
--- /dev/null
+++ b/dev/src/dev/explain.clj
@@ -0,0 +1,18 @@
+(ns dev.explain
+  (:require
+   [clojure.string :as str]
+   [honey.sql :as sql]
+   [toucan2.core :as t2]))
+
+(defn explain-query
+  "Explain a sql query or a honeysql query with option to analyze the query."
+  ([queryable]
+   (explain-query queryable false))
+  ([queryable analyze?]
+   (->> (t2/query
+         (str/join
+          " "
+          (remove nil? ["EXPLAIN"
+                        (when analyze? "ANALYZE")
+                        "(" (if (map? queryable) (first (sql/format queryable {:inline true})) queryable) ")"])))
+        (map #(get % (keyword "query plan"))))))
diff --git a/src/metabase/api/search.clj b/src/metabase/api/search.clj
index 99d20416afc8f0cd097a81ee0f467d8cb292bcbd..167074cc64f26faeee0dff290ff70582451a0db7 100644
--- a/src/metabase/api/search.clj
+++ b/src/metabase/api/search.clj
@@ -139,7 +139,7 @@
     query))
 
 (mu/defn ^:private replace-select :- :map
-  "Replace a select from query that has alias is `target-alias` with the `with` column, throw an error if
+  "Replace a select from query that has alias is `target-alias` with [`with` `target-alias`] column, throw an error if
   can't find the target select.
 
   This works with the assumption that `query` contains a list of select from [[select-clause-for-model]],
@@ -148,15 +148,16 @@
   This function then will replace the dummy column with alias is `target-alias` with the `with` column."
   [query        :- :map
    target-alias :- :keyword
-   with         :- [:or :keyword [:sequential :any]]]
-  (let [selects (:select query)
-        idx     (first (keep-indexed (fn [index item]
-                                       (when (and (coll? item)
-                                                  (= (last item) target-alias))
-                                         index))
-                                     selects))]
+   with         :- :keyword]
+  (let [selects     (:select query)
+        idx         (first (keep-indexed (fn [index item]
+                                           (when (and (coll? item)
+                                                      (= (last item) target-alias))
+                                             index))
+                                         selects))
+        with-select [with target-alias]]
     (if (some? idx)
-      (assoc query :select (m/replace-nth idx with selects))
+      (assoc query :select (m/replace-nth idx with-select selects))
       (throw (ex-info "Failed to replace selector" {:status-code  400
                                                     :target-alias target-alias
                                                     :with         with})))))
@@ -165,13 +166,24 @@
   [query :- :map
    model :- [:enum "card" "dataset" "dashboard" "metric"]]
   (-> query
-       (replace-select :last_editor_id [:r.user_id :last_editor_id])
-       (replace-select :last_edited_at [:r.timestamp :last_edited_at])
+       (replace-select :last_editor_id :r.user_id)
+       (replace-select :last_edited_at :r.timestamp)
        (sql.helpers/left-join [:revision :r]
                               [:and [:= :r.model_id (search.config/column-with-model-alias model :id)]
                                [:= :r.most_recent true]
                                [:= :r.model (search.config/search-model->revision-model model)]])))
 
+(mu/defn ^:private with-moderated-status :- :map
+  [query :- :map
+   model :- [:enum "card" "dataset"]]
+  (-> query
+      (replace-select :moderated_status :mr.status)
+      (sql.helpers/left-join [:moderation_review :mr]
+                             [:and
+                              [:= :mr.moderated_item_type "card"]
+                              [:= :mr.moderated_item_id (search.config/column-with-model-alias model :id)]
+                              [:= :mr.most_recent true]])))
+
 ;;; +----------------------------------------------------------------------------------------------------------------+
 ;;; |                                      Search Queries for each Toucan Model                                      |
 ;;; +----------------------------------------------------------------------------------------------------------------+
@@ -191,7 +203,8 @@
                               [:= :bookmark.user_id api/*current-user-id*]])
       (add-collection-join-and-where-clauses :card.collection_id search-ctx)
       (add-card-db-id-clause (:table-db-id search-ctx))
-      (with-last-editing-info model)))
+      (with-last-editing-info model)
+      (with-moderated-status model)))
 
 (defmethod search-query-for-model "action"
   [model search-ctx]
diff --git a/src/metabase/search/config.clj b/src/metabase/search/config.clj
index 41dbfdfafc3a8062a1f8cc583c395368fc04b40a..ce6ba9cc5780196cbd6f3ebff1695123046c807d 100644
--- a/src/metabase/search/config.clj
+++ b/src/metabase/search/config.clj
@@ -245,7 +245,8 @@
    [:table.description :table_description]])
 
 (defmulti columns-for-model
-  "The columns that will be returned by the query for `model`, excluding `:model`, which is added automatically."
+  "The columns that will be returned by the query for `model`, excluding `:model`, which is added automatically.
+  This is not guaranteed to be the final list of columns, new columns can be added by calling [[api.search/replace-select]]"
   {:arglists '([model])}
   (fn [model] model))
 
@@ -264,17 +265,6 @@
   (conj default-columns :collection_id :collection_position :dataset_query :creator_id
         [:collection.name :collection_name]
         [:collection.authority_level :collection_authority_level]
-        [{:select   [:status]
-          :from     [:moderation_review]
-          :where    [:and
-                     [:= :moderated_item_type "card"]
-                     [:= :moderated_item_id :card.id]
-                     [:= :most_recent true]]
-          ;; order by and limit just in case a bug violates the invariant of only one most_recent. We don't want to
-          ;; error in this query
-          :order-by [[:id :desc]]
-          :limit    1}
-         :moderated_status]
         bookmark-col dashboardcard-count-col))
 
 (defmethod columns-for-model "indexed-entity" [_]
diff --git a/src/metabase/search/filter.clj b/src/metabase/search/filter.clj
index 1fb2301656ae49f31314b12961a980a3b3e2ed39..cb3d2902c66f66577f29f856276fbe64df0186eb 100644
--- a/src/metabase/search/filter.clj
+++ b/src/metabase/search/filter.clj
@@ -189,6 +189,13 @@
   [query join-type table]
   (->> (get query join-type) (partition 2) (map first) (some #(= % table)) boolean))
 
+(defn search-model->revision-model
+  "Return the apporpriate revision model given a search model."
+  [model]
+  (case model
+    "dataset" (recur "card")
+    (str/capitalize model)))
+
 (doseq [model ["dashboard" "card" "dataset" "metric"]]
   (defmethod build-optional-filter-query [:last-edited-by model]
     [_filter model query editor-ids]
diff --git a/test/metabase/api/search_test.clj b/test/metabase/api/search_test.clj
index a8136ce24995f039e05802cd3a969444122db8b8..47886a1cb7c82be400d65d9809ce194669ac9ea2 100644
--- a/test/metabase/api/search_test.clj
+++ b/test/metabase/api/search_test.clj
@@ -13,6 +13,7 @@
             PermissionsGroupMembership Pulse PulseCard QueryAction Segment Table]]
    [metabase.models.collection :as collection]
    [metabase.models.model-index :as model-index]
+   [metabase.models.moderation-review :as moderation-review]
    [metabase.models.permissions :as perms]
    [metabase.models.permissions-group :as perms-group]
    [metabase.models.revision :as revision]
@@ -371,6 +372,22 @@
       (is (= dashboard-count-results
              (set (unsorted-search-request-data :rasta :q "dashboard-count")))))))
 
+(deftest moderated-status-test
+  (let [search-term "moderated-status-test"]
+    (mt/with-temp [:model/Card {card-id :id} {:name "moderated-status-test"}]
+      ;; an item could have multiple moderation-review, and it's current status is defined as
+      ;; moderation-review.most_recent, so we creates multiple moderation review here to make sure
+      ;; test result return the most recent status and don't duplicate the result
+      (doseq [status ["verified" nil "verified"]]
+        (moderation-review/create-review! {:moderated_item_id   card-id
+                                           :moderated_item_type "card"
+                                           :moderator_id        (mt/user->id :crowberto)
+                                           :status              status}))
+      (is (=? [{:id               card-id
+                :model            "card"
+                :moderated_status "verified"}]
+              (:data (mt/user-http-request :crowberto :get 200 "search" :q search-term)))))))
+
 (deftest permissions-test
   (testing (str "Ensure that users without perms for the root collection don't get results NOTE: Metrics and segments "
                 "don't have collections, so they'll be returned")