ドキュメントデータベースをLuceneで構築する


「アーカイブ」システムといえば、ドキュメント・データベースを選ぶのが最適です.ドキュメントデータベースといえばMongoDB、CouchDBなどが一般的ですが、ここで言うのはこれではなく、もう一つのNoSQL「ドキュメントデータベース」--Luceneです.引用符を打つのは、まだ人の言うことを聞いていないからだ.
  • 需要
  • 最近、会社は内部検索をして、いろいろな案を比較した後、Luceneを使うことにしました.最初のプロトタイプを作った後、会社の他のいくつかのプロジェクトが将来使うかもしれないことを考慮して、コードをもう一度書くのは私のスタイルではありません.また開梱即用のSolrを試してみましたが、それも私の料理ではないと思いました.私のプロジェクトにはすでにSolrのようなSchameの構成が使われているので、このモジュールを多重化するつもりです.インタフェース仕様私も既存の仕様を多重化するつもりです.
    基礎の添削は比較的簡単で、すぐに原型を作った.この時、私は会社のもう一つの大きなモジュールを考えました.ファイル(履歴書と呼ばれています).このセクションでは、MongoDBで再構築することを考慮して、別のプロジェクトの類似モジュールと統合する計画を立てています.Luceneが複雑なデータ構造にアクセスできる以上,この機会にLuceneをアーカイブシステムの最下位サポートとして検討してみよう.
    ここで言ったファイルはどうなっていますか?簡単な例として、履歴書を挙げます.
      :XXX
      : 
      :xxx/xxx.jpg
        
          :  、  、XX   
          :              ,        
        
          1
                : 2014/1/1~2015/1/1
              : Jiali.Dun
              :    
              :  
          2……
    

    大体のドキュメント構造はこのようにして、フィールド、階層は不確定で、この構造を維持する必要があります.保存、取得できます.ほとんどのフィールドはクエリー、ソートできます.
  • 構造化データ
  • 以上のファイル構造をまとめると、構成上は次のように分けることができます.
    a.     (  ,  ,  )
    b.     (  ,     )
    c.     (    )
    

    上では特に基礎情報を基礎「プレート」と呼んでいます.つまり、一般的には1つのファイルは複数のプレートから構成されています.趣味の下でスポーツ、娯楽に分けるなど、ファイルはもっと複雑かもしれません.このような区分は、ストレージから言えば2階建ての設計と変わらず、親プレートの指向が1つ増えただけですが、表現の複雑さが増しています.今みんなはすべて“扁平化”について話して、私の理解した扁平はアイコンを扁平にしただけではなくて、更に情報の取得のルートが扁平になって、私に見せて、私に1階のメニューを注文して中に入ってまた1階を注文させないでください;ラベル、検索でフィルタできるものは、ディレクトリツリーをクリックして検索させないでください.
    1つのプレートは、キー値ペアのセットです.ここでは、このルールのセットをフォームと呼びます.では、リストプレートは、複数の繰り返し可能なフォームからなるプレートです.
    フィールドには次のものがあります.
    a.   
    b.   
    c.   
    d.   、  (  )
    e.   、  
    f.     (  、  、   )
    

    a~eからはよくあるタイプで、ファイルはファイルサーバにダンプできますが、ここではURLだけを保存します.日付、時刻はタイムスタンプに変換できます.fとは、このフィールドの値が複数入力可能であり、通常、複数の記録が必要なものを記録するために使用され、記憶上は複数選択と同じである.
    Luceneはもともと1つのフィールドに複数の値を格納できるのが素晴らしいです.
  • フォームおよび検証
  • 前述したように、データ構造の説明は以下の通りです.
      1
          1:  ,    ,    ,      
          2……
      1
          1:  
          2……
    

    栗を一つ挙げます.
        
          :  ,  ,   ,    100
          :  ,  ,   ,    
          :  ,  ,   ,  (jpg,png)
            :  ,  ,   ,      
            :  ,  ,   ,      
        
        0: 
        1: 
        2:  
          
          :  ,  ,   ,    50
          :  ,  ,   ,    
          
            :    ,  ,   
          :  ,  ,   
          :  ,  ,   
    

    このフォーム記述も編集と解析を容易にするために、コードネストではなくリンクネストを使用するフォーム->フィールドの2層構造に設計されています.検証器が検証するとき、フィールドタイプがフォームであることを発見し、対応するフォームを取り出して再帰すればよい.こんなに多くのフォームが積み上げられているのに、どうやってネーミングスペースの問題を解決しますか?各モジュール(同じ適用トピック)に対して、フォームを処理するときにモジュール名(構成名)が指定されていない場合は、現在のモジュールの指定名のフォーム、ある場合は指定モジュールの下のフォームを取るように設計しました.
    データは検査に成功した後、以下のJSONのような構造に整理されます.
    {
        "name": "XXX",
        "gender": 1,
        "photo": "upload/photo/xxxxxx.jpg",
        "hobby": {
            "interest": [
                "ljsdfsdfsd",
                "sldfj2ef"
            ],
            "comment": "sjldfjsldfsdlfjsldfsdfsdfsdfsdfsdf"
        },
        "education": [
            {
                "date": {
                    "begin": Date(2014/1/1), 
                    "end": Date(2015/1/1)
                },
                "university": "lwnfdsfwe",
                "professional": "slwef"
            }
        ]
    }
    

    入力されたデータ構造はこれと一致しており、アプリケーション/x-www-form-urlencoded形式でコミットされたデータについては、PHPの要求パラメータ解析方式のように「.」、「[」、「]」に基づいて上記のデータ構造に解析することができる.
  • 記憶方式
  • はい、もうたくさん話しました.これから本題に入ります.データはすべて整理しましたが、このような構造のデータはどのようにLucene検索ライブラリに保存されますか?LuceneはモンゴDBがBSONを格納できるような複雑な構造ではないですね.リレーショナル・データベースを設計するERMのように、テーブルが使用されるときにいくつかのインデックス・ディレクトリを作成し、外部キーで関連付け、自分で関連クエリーを実現するのではないでしょうか.あるいは、データのシーケンス化全体を1つのフィールドに捨てて、自分でFilter、Queryを書いて複雑な構造に対するクエリーを実現しますか?
    そんなに苦労したくない.
    これらの問題を解決するには、まず、Luceneの基本フィールドのタイプを整理します.
    StringField:       ,       
    StoredField:       (       、            )
    TextField  :           ,        
    

    他にもIntField、FloatField・・数字を保存できる(肝心なのは数字の値の大きさでソートできる)、ByteFieldはバイナリデータなどを保存できる.また、Luceneは1つのフィールドに複数の値を格納することをサポートしており、1つの価値がある場合に1つだけ持つと、複数の値が必要な場合に複数の値を取得します.
    デフォルトでは、ベース・データが独立してインデックス化され、クエリーが容易になり、個別のフィールドで保存されると仮定できます.他のデータは、フィールド名にプレート名とフィールド名を区切り記号で接続できます.これらのフィールドのフィールド名が重複しない(ランダムに生成されるなど)場合は、フィールド名を直接使用します.このような利点は、フィールドのデータがAプレートからBプレートに移行すると、過去に格納されていたデータを変更する必要がなく、この移行は視覚的な移行にすぎないため、表示と格納の分離です.現在、私がRDMSで実現しているアーカイブシステムはこのようにしています.
    面倒なのはリストプレートです.
    このセクションのデータをクエリーする必要がない場合は、直接シーケンス化して保存します.
    内部の独立したフィールドを検索してソートする必要がある場合は、シーケンス化した上で、インデックスを格納するフィールドを1つ追加します.例えば、フィールド教育経験-学校を追加すると、ある学校に通ったファイルを検索することができます.
    また、需要を完了したい場合は、日付範囲内で○○学校に通っているファイルを検索し、別途保存しましょう.クエリーでは外部キーで関連付けることができ、1つを検出してからINを検索することができます(注:LuceneにはINの操作がなく、MUSTとSHOULDを併用する必要があります).アーカイブとして現在のインデックス・ディレクトリに追加することもできます.より良い方法は、プライマリ・データがよりきれいになるように、付属ディレクトリ・ストレージを独立して開くことです.
    完全なストレージ構造は次のとおりです.
          
          ID
          1: 1, 2……
          2……
          
           ID
           ID
          
          1: 1, 2……
          2……
    
  • クエリー規則
  • RDBMSモデルに適用されているクエリー・ルールがあります.ルールをLuceneのQueryに解析する必要があります.クエリー・ルールは次のとおりです.
    {
        "id": "xxx",       //   
        "star": [1, 2],    // IN, Lucene   Must + Should
        "f1": {
            "-gt": 18,     //   
            "-le": 35      //      
        },
        "f2": {
            "-ne": "zzz"   //    
        },
        "f3": {
            "-or": "zzz"   // OR,    Lucene   Should
        },
        "f4": {
            "-ni": [3, 4]  // NOT IN,    Lucene   Must_Not
        },
        "f5": {
            "-ai": [1, 2]  // ALL IN,    Lucene   Must
        },
        "f6": {
            "-oi": [5, 6]  // OR IN,    Lucene   Should
        }
    }
    

    アプリケーション/x-form-urlencodeでは、次のように表されます.
    id=xxx&star[]=1&star[]=2&f1[-gt]=18&f1[-le]=35&f6[-oi][]=5&f6[-oi][]=6
    

    システムはPHPのような要求パラメータ解析方式で上のJSONのようなデータ構造を解析する.読みやすく書くために[]を.に置き換えることもサポートされています.例えば、f 6.-oi.=6はf 6[-oi]=6と同じです.
    MongoDBに詳しい人はこれをよく知っています.間違いありません.これはMongoDBから参考にして、私の関係データベースのクエリーに使います.ここでの-orと-oiはLucene特有で、ソートに影響を与えることができ、有無のフィールドを検索するのに役立ちます.-aiはMongoのcontainsAllに似ています.
    注意:[2015/12/01]以上の"-"は"!"記号に変換されました.
  • インタフェース仕様
  • インタフェースの主な目的は、データを伝達するためであり、データ構造はすでに上に示されている.インタフェースはRESTスタイルで与えられ、要求データはアプリケーション/x-form-urlencode,jsonをサポートし、返されるデータはjsonである.
    Protobufに詳しいなら、上記のフォームがprotoの説明に似ていることに気づいたかもしれません.間違いありません.これも参考になります.ただProtobufはこれ以上説明できないので、私は使いませんでした.ここでのフォーム構成はproto記述に変換できます.異なるシステム、異なる端末のデータ交換を容易にするために、protobufもインタフェースサポート内に存在する.
  • 後注
  • Luceneの書き込みロックの「問題」を考えなければ、かなり良い埋め込みドキュメントデータベースだと思います.複雑な構造データをLuceneで格納する可能性はまだ議論されているが,Luceneを理解するのに苦労することは価値がある.何かの言語、フレームワーク、ツールで何かを完成させなければならないことを強要する必要はありませんが、実際には一つのことをする方法がたくさんあります.もっと考えを試してみると、もっとはっきりしています.
    githubにプロジェクトがありますが、まだプレゼンテーションを構築していません.後でリンクを追加します.
    部分コード:
    Lucene CRUDパッケージ:https://github.com/ihongs/Hon...フォーム検証プログラム:https://github.com/ihongs/Hon...フォーム構成仕様:https://github.com/ihongs/Hon...
    参考資料:
    MongoDBクエリー:http://docs.mongodb.org/manua...Lucene クエリー:https://lucene.apache.org/cor...REST 概要:http://baike.baidu.com/view/5...PHP 要求パラメータ解析(第1条Note参照):http://php.net/manual/zh/rese...