1

Common Lisp で最初の一歩を踏み出しました。clouchdb http://common-lisp.net/project/clouchdb/#examplesに感謝します。

私はcouchdbからいくつかの単純なデータを取得することができました

      (invoke-view "hulk" "hulk" )
 ((:|total_rows| . 2) (:|offset| . 0) (:|rows| ((:|id| . "gjc") (:|key| . "hulk") (:|value|                             
 (:|_id| . "gjc2321o3io13") (:|_rev| . "3-b6433781c65460f2c9b1f1a153953171")
  (:NAME . "Dr Bruce Banner") (:|kind| . "users") (:|username| . "hulk") (:|title| . "gamma r adia
 tions: what to do ?"))) ((:|id| . "irnmn239223") (:|key| . "ironman") (:|value| (:|_id| . "irnmn2     39223") 

  (:|_  rev| . "5-2b6cf739d24b1208fe8eca70e37ffdc9") (:|name| . "tony stark") (:|title| . 
(:|name| . "tony stark") (:|title| . "why iphone 5 sucks - but i own one \"") (:|kind| . "users") (:|username| . "ironman") (:|text| .  "welcome to post number one ......")))))

7 >

SEXML を使用して HTML レコードを表示しているので、HTML 表示テンプレートは次のようになります

 ;;static here 
 (<:h2 "((LISP RETRO BLOG))")
 (<:h3 "(( ***** RETRO BUT STILL COOL *****))")
 (<:p "( (MADE IN LISP ))")
 (<:p "READY.")
 (<:img :src "/img/prompt.gif" :alt "cursor"))
 ;;this is a variable
 (<:p "universal time: " mytime) 

ここで、上記の結果 (たとえば、ユーザー名は Ironman と Hulk) を介して単純なループを作成し、次のようなものを表示しますか?

  (<:p "Welcome!" username) 

最終的には非常に単純なループになる可能性のあるコードを大量に投稿して申し訳ありません。例 ( http://psg.com/~dlamkins/sl/chapter05.html ) やその他のリソースを読んで試してみましたが、おそらく非常に基本的なものが欠けているので、助けていただければ幸いです。スキーマを持ついくつかのレコードをループするのとまったく同じではないため、couchdb ドキュメントには異なるフィールドが含まれている可能性があることに注意してください。これは関連する可能性があります。たとえば、ドキュメントがブログ投稿である場合、タグが含まれる場合と含まれない場合があるため、ドキュメントで使用可能なすべてのデータ (おそらく _id を除く) を含むページを表示または作成することができます。

不明な点がある場合は、コメントしてください。喜んで質問を編集します。

前もって感謝します !

4

2 に答える 2

2

出力データを読みやすい形式に再フォーマットすると、出力データをよりよく理解できるようになります。このような:

((:|total_rows| . 2) (:|offset| . 0)
 (:|rows|
   ((:|id| . "gjc") (:|key| . "hulk")
    (:|value|
      (:|_id| . "gjc2321o3io13")
      (:|_rev| . "3-b6433781c65460f2c9b1f1a153953171")
      (:NAME . "Dr Bruce Banner")
      (:|kind| . "users")
      (:|username| . "hulk")
      (:|title| . "gamma radiations: what to do ?")))
   ((:|id| . "irnmn239223") (:|key| . "ironman")
    (:|value|
      (:|_id| . "irnmn2     39223") 
      (:|_  rev| . "5-2b6cf739d24b1208fe8eca70e37ffdc9")
      (:|name| . "tony stark")
      (:|title| .

      ;; here you repeat name and title, so the previous and next lines are erroneous

      (:|name| . "tony stark")
      (:|title| . "why iphone 5 sucks - but i own one \"")
      (:|kind| . "users")
      (:|username| . "ironman")
      (:|text| .  "welcome to post number one ......")))))

したがって、clouchdb を介して CouhcDB から取得したものは 、Lisp 用語でalistと呼ばれる、特別に構造化されたリストです。連想リストを操作するための一連の関数があり、その中で最も重要なものはASSOC.

結果は、2 つの行があり、それぞれが別の連想リストとしてデータを保持していることを示しています。それらを反復するには、次の関数を使用できます。

(defun maprows (fn data)
  (mapcar fn (cdr (assoc :|rows| data))))

ここで、1 つの引数MAPROWSの関数に渡す必要があります。FNたとえば、適切な方法で値を出力したい場合は、次の関数を渡すことができます。

(defun print-row (record)
  (dolist (pair (cdr (assoc :|value| record)))
    (format t "~A: ~A~%" (car pair) (cdr pair)))
  (terpri))

それがどのように機能するか見てみましょう:

CL-USER> (maprows 'print-row
                  '((:|total_rows| . 2) (:|offset| . 0)
                    (:|rows|
                     ((:|id| . "gjc") (:|key| . "hulk")
                      (:|value|
                        (:|_id| . "gjc2321o3io13")
                        (:|_rev| . "3-b6433781c65460f2c9b1f1a153953171")
                        (:NAME . "Dr Bruce Banner")
                        (:|kind| . "users")
                        (:|username| . "hulk")
                        (:|title| . "gamma radiations: what to do ?")))
                     ((:|id| . "irnmn239223") (:|key| . "ironman")
                      (:|value|
                        (:|_id| . "irnmn2     39223") 
                        (:|_rev| . "5-2b6cf739d24b1208fe8eca70e37ffdc9")
                        (:|name| . "tony stark")
                        (:|title| . "why iphone 5 sucks - but i own one \"")
                        (:|kind| . "users")
                        (:|username| . "ironman")
                        (:|text| .  "welcome to post number one ......"))))))
_id: gjc2321o3io13
_rev: 3-b6433781c65460f2c9b1f1a153953171
NAME: Dr Bruce Banner
kind: users
username: hulk
title: gamma radiations: what to do ?

_id: irnmn2     39223
_rev: 5-2b6cf739d24b1208fe8eca70e37ffdc9
name: tony stark
title: why iphone 5 sucks - but i own one "
kind: users
username: ironman
text: welcome to post number one ......

(NIL NIL)

ご覧のとおり、 は、基になる と同様MAPROWSに、 の適用結果も収集します。FNMAPCAR

于 2012-10-02T05:04:25.067 に答える
2

これは少し異なるアプローチですが、私はそれに完全に満足しているわけではありません。おそらく誰かが私を修正したり、より良い方法を提案したりするでしょうが、この全体的な戦略はオブジェクト マッピングとして知られています。つまり、データベース内のテーブルからデータを取得する場合、アプリケーション ロジックをプログラムする言語でより快適なオブジェクトを作成します。

皮肉なことに、CouchDB はこの段階を超えるはずでした。CouchDB はオブジェクトを JSON 形式にエンコードするため、一般的に使用されている JavaScript に対して「ネイティブ」になります。しかし、CL で受け取った形式は、操作が快適ではありません/オブジェクトの適切なネイティブ表現ではありません。さて、クライアント ブラウザ アプリケーションでは CL を使用できないため、あなたの組み合わせには意味がありません... つまり、サーバー側では何も得られません (ほとんどの場合、パフォーマンスが低下します)。 -賢明ですが、これはあなたの個人的なブログであるため、これは問題になる可能性は低いです)。

したがって、以下は単純なオブジェクト マッピングの試みです。

(defclass db-object () ())

(defun slot-list-from-query (query)
  (mapcar
   #'(lambda (pair)
       (let ((name (string-upcase (symbol-name (car pair)))))
         (list (intern name)
               :accessor
               (intern (concatenate 'string name "-OF"))
               :initarg (intern name "KEYWORD")))) (eval query)))

(defmacro table-to-class (name describe-table-query)
  `(let ((db-class (defclass ,name (db-object)
                     ,(slot-list-from-query describe-table-query))))
     (defmethod initialize-instance :after ((object ,name) &key raw-data)
                (mapcar
                 #'(lambda (pair)
                     (setf (slot-value object
                                       (find-symbol
                                        (string-upcase
                                         (symbol-name (car pair)))))
                           (cdr pair))) raw-data))
     db-class))

(defparameter *raw-data*
  '((:|total_rows| . 2) (:|offset| . 0)
    (:|rows|
     ((:|id| . "gjc") (:|key| . "hulk")
      (:|value|
        (:|_id| . "gjc2321o3io13")
        (:|_rev| . "3-b6433781c65460f2c9b1f1a153953171")
        (:|name| . "Dr Bruce Banner")
        (:|kind| . "users")
        (:|username| . "hulk")
        (:|title| . "gamma radiations: what to do ?")))
     ((:|id| . "irnmn239223") (:|key| . "ironman")
      (:|value|
        (:|_id| . "irnmn2     39223") 
        (:|_rev| . "5-2b6cf739d24b1208fe8eca70e37ffdc9")
        (:|name| . "tony stark")
        (:|title| . "why iphone 5 sucks - but i own one \"")
        (:|kind| . "users")
        (:|username| . "ironman")
        (:|text| .  "welcome to post number one ......"))))))

(table-to-class example-mapping (car (cdaddr *raw-data*)))
(id-of (make-instance 'example-mapping :id "foo")) ; foo
(id-of (make-instance 'example-mapping :raw-data (car (cdaddr *raw-data*)))) ; gjc

自由にデータを「修正」して、一貫性が見えるようにしました。evalまた、通常、コードを実行する前にテーブルの説明があるため、実行時にクラスを宣言するという面倒な作業全体が、展開前に行う機械的な操作に軽減され、これには必要ありません。大きい。あなたが持っている情報を保存し、コードが展開された後に受け取ったかのように見えるようにするために、このように投稿しました。

使用したい場合は、削除evalして次のようにします。

(table-to-class example-mapping ((name-1 . value-1) (name-2 . value-2) ...))
于 2012-10-02T09:31:10.497 に答える