在Datomic中跨多个属性进行全文搜索

Iva*_*aev 7 clojure datomic

我有一个看起来大致相似的模型(在JSON中):

{"gender": "female", 
 "name": [
  {"family": "Smith", 
   "given": ["Samantha"], 
   "middle": ["Lee"]]}}
Run Code Online (Sandbox Code Playgroud)

有大约6M的记录具有这样的结构.我需要使用OR子句在人名的所有组件上提供全文搜索.例如,如果用户输入"smith",我需要检查所有给定,中间和姓氏.

在Datomic中,我制作了一个模式:

   {:db/ident       :model/name
    :db/valueType   :db.type/ref
    :db/isComponent true
    :db/cardinality :db.cardinality/many}

   {:db/ident       :model.name/family
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one
    :db/fulltext    true}

   {:db/ident       :model.name/given
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/many
    :db/fulltext    true}

   {:db/ident       :model.name/middle
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/many
    :db/fulltext    true}          
Run Code Online (Sandbox Code Playgroud)

注意,我提供了这些属性的全文索引.现在,当我通过单个属性查询时family,性能很好(大约100ms):

(def query-all
  '[:find [(rand 100 ?model) ...]
    :in $ ?search
    :where
    [(fulltext $ :model.name/family ?search) [[?name _ _ _]]]
    [?model :model/name ?name]])
Run Code Online (Sandbox Code Playgroud)

但是当我使用OR子句添加其他条件时,性能会急剧下降(20秒):

(def query-all
  '[:find [(rand 100 ?model) ...]
    :in $ ?search
    :where
    (or
     [(fulltext $ :model.name/family ?search) [[?name _ _ _]]]
     [(fulltext $ :model.name/given ?search) [[?name _ _ _]]]
     [(fulltext $ :model.name/middle ?search) [[?name _ _ _]]])
    [?model :model/name ?name]])
Run Code Online (Sandbox Code Playgroud)

我的问题是,我怎么能改善它?

如果我们更进一步,那么也不仅仅是通过名称,而是通过地址的组件找到它也会很棒.理想情况下,会有以下查询(也很慢):

(def query-all
  '[:find [(rand 100 ?model) ...]
    :in $ ?search
    :where
    (or

     (and
      [(fulltext $ :model.name/given ?search) [[?e _ _ _]]]
      [?p :model/name ?e])

     (and
      [(fulltext $ :model.name/middle ?search) [[?e _ _ _]]]
      [?p :model/name ?e])

     (and
      [(fulltext $ :model.name/prefix ?search) [[?e _ _ _]]]
      [?p :model/name ?e])

     (and
      [(fulltext $ :model.name/suffix ?search) [[?e _ _ _]]]
      [?p :model/name ?e])

     (and
      [(fulltext $ :model.name/family ?search) [[?e _ _ _]]]
      [?p :model/name ?e])

     (and
      [(fulltext $ :model.address/city ?search) [[?e _ _ _]]]
      [?p :model/address ?e])

     (and
      [(fulltext $ :model.address/state ?search) [[?e _ _ _]]]
      [?p :model/address ?e]))])
Run Code Online (Sandbox Code Playgroud)

我该如何实现?

小智 4

我们处于同样的情况,最终使用了一种解决方法:

我们创建了一个连接所有其他字符串属性的属性。当然,使用该属性的全文进行查询。

  • 这并不是要求澄清,而是提出解决方法。这不是“没有答案”。 (2认同)