【问题标题】:insert json data into postgresql db with postmodern使用 postmodern 将 json 数据插入 postgresql db
【发布时间】:2013-11-07 00:00:02
【问题描述】:

我想在我的数据库中插入大量 JSON 数据。

[{
    "term": "wine",
    "name": "Bubba Wine & Spirits",
    "address": "1234 N San Fake Rd,"
}, {
    "term": "wine",
    "name": "Wine Shop",
    "address": "123 N Not Real Blvd,"
}]

我使用cl-json 转换为lisp 对象。

(defvar *data*
  (decode-json (open "my-json-file.json")))

结果如下:

(((:TERM . "wine") (:NAME . "Bubba Wine & Spirits")
  (:ADDRESS . "1234 N San Fake Rd,"))
 ((:TERM . "wine") (:NAME . "Wine Shop")
  (:ADDRESS . "123 N Not Real Blvd,")))

Postmodern 在此处列出了一种使用insert-rows-into 插入多行的方法:https://sites.google.com/site/sabraonthehill/postmodern-examples/postmodern-insert#multiple-row-inserts

(:insert-rows-into 'table :columns 'a 'b :values '((10 20) (30 40)))

这不是默认的 JSON 格式。

看来我有两个选择:

  1. 按摩数据以适应
  2. 找到一个按原样处理的函数。

我怀疑:insert-rows-into 做了我想做的事,但我不太确定如何把它塞进去。

【问题讨论】:

    标签: sql json postgresql lisp common-lisp


    【解决方案1】:

    这有帮助吗?

    (defun compose (&rest fns)
      (lambda (x)
        (reduce #'funcall fns :initial-value x :from-end t)))
    
    (defun quotify (x)
      `',x)
    
    (defun guess-columns (data *package*)
      (mapcar (compose #'quotify #'intern #'symbol-name #'first) (first data)))
    
    (defun guess-values (data)
      (loop for x in data collect (mapcar #'cdr x)))
    
    (defun insert-rows (data package)
      `(:insert-rows-into 'table :columns ,@(guess-columns data package)
                      :values ',(guess-values data)))
    

    用您的*data* 调用insert-rows 会得到结果

    (:INSERT-ROWS-INTO 'TABLE :COLUMNS 'TERM 'NAME 'ADDRESS :VALUES
     '(("wine" "Bubba Wine & Spirits" "1234 N San Fake Rd,")
       ("wine" "Wine Shop" "123 N Not Real Blvd,")))
    

    【讨论】:

      【解决方案2】:

      您可以修改解析器的行为以产生您需要的输出,应该这样做:

      (defun json->insert ()
        (labels ((%string->symbol (s) (intern (string-upcase s))))
          (let (keys values row)
            (json:bind-custom-vars
                (:object-key
                 (lambda (key)
                   (unless (member key keys :test #'equal)
                     (push key keys)))
                 :object-value
                 (lambda (value) (push value row))
                 :end-of-object
                 (lambda () (setf values (cons row values) row nil)))
              (json:decode-json-from-string
               "[{
          \"term\": \"wine\",
          \"name\": \"Bubba Wine & Spirits\",
          \"address\": \"1234 N San Fake Rd,\"
          }, {
          \"term\": \"wine\",
          \"name\": \"Wine Shop\",
          \"address\": \"123 N Not Real Blvd,\"
          }]"))
            (list (mapcar #'%string->symbol keys) values))))
      
      ;; (json->insert)
      ;; ((ADDRESS NAME TERM)
      ;;  (("123 N Not Real Blvd," "Wine Shop" "wine")
      ;;   ("1234 N San Fake Rd," "Bubba Wine & Spirits" "wine")))
      

      但是,在我看来,cl-json 被过度设计了,您最好使用类似cl-yacc 的东西来构建临时解析器并完成它。我知道建议重新发明某些东西是一件很奇怪的事情,尤其是当已经有了一个工具时,但这就是我最终在某个时候做的事情(我需要一个拉式解析器)。但我鼓励您运用自己的判断。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-06
        • 1970-01-01
        • 2020-09-13
        • 2017-08-17
        • 1970-01-01
        • 2019-11-20
        • 2021-10-16
        • 1970-01-01
        相关资源
        最近更新 更多