2016-05-17 2 views
1

私は自分のプロジェクトでLucene.NETを使用しています。今はちょっと厄介な星座です。私はLuceneの-指数の文書として文書やダッシュなどのエンティティーの活動を格納しています2つのLucene-Documentsで検索

public class Dash { 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public int ActivityId { get; set; } 
    public string Username { get; set; } 
} 

public class Activity { 
    public int Id { get; set; } 
    public string Subject { get; set; } 
} 

:私は2つのエンティティを持っています。

さて、私は今

+Subject:"Appointment-Invitation" 

よう

+Description:"Appointment" +Username:"mm" 

や活動のエントリのようなダッシュのエントリを検索することができ、私は両方のドキュメント上でダッシュエントリを検索する必要があります。たとえば、ユーザ名が「mm」で、Descriptionに文字列「Appointment」があるか、関連するアクティビティ - エンティティのSubjectに「Appointment」があるすべてのDash-Entriesを検索する必要があります。 SQL(Pseudo)では、これは次のようになります。

... where Dash.UserName = 'mm' and (Dash.Description like 'Appointment%' or Dash.Activity.Subject like 'Appointment%' 

誰かが私に助けてくれますか?Lucene.NETでどうすればいいですか?おそらく、Lucene.NET-Indexに別の方法で文書を保存する必要がありますか?

+0

「AND」、「OR」演算子を使用できます。ユーザー名:mm **および**(説明:予定**または**件名:予定) – Eser

+0

ユーザー名と件名はLucene.NETの同じ文書ではありません。これもこの方法で動作していますか? – BennoDual

+0

私はあなたが求めているものは得られませんが、あなたの擬似SQL stmtと同等です。 – Eser

答えて

0

同じインデックス

に別のエンティティタイプを入れたときにあなたが世話をする必要がありますが、「ID:1」で検索した場合、あなたがダッシュまたはアクティビティを取得してきた場合はどのようにあなたが知っているのですか?

次のいずれかのフィルタとして: "アクティビティ_type": "ダッシュ_type" かを

  • するフィールド名が "dash_id"、
  • "_type" フィールドを追加し、追加し、 "ACTIVITY_ID" すなわち一意であることを確認検索

に現在のLucene.net(3.0.3)

のLuceneは、少なくともであなたの単一のクエリに「参加」を行うことはできませんドキュメントデータストアは、キー値ストアのようなものです。それぞれの文書は "単なるフィールドの束"です。

各エンティティを照会するだけで、Linqを使って2つのコレクションを結合することができます。しかし、これは非常に非効率的でメモリを大量に消費することがあります。すべての結果は、期待する結果の数に依存します。数字が低い場合、これはおそらく最も簡単です。

しかし、2つのクエリと「同期した列挙型」を使用すると、かなりうまくいくことができます。警告:これは、「ダッシュ」は何であるか言うのは難しいですが、私はそれぞれの活動のために多くのダッシュがちょうどオフに書かれていた

擬似コード

// assuming "query" returns a TopDocs 
var dashDocs = query "+dash_username:mm +dash_description:Appointment" sort by "dash_ActivityId" 
var activityDocs = query "+dash_username:mm +dash_description:Appointment" sort by "activity_Id" 

var dashDocsEnum = dashDocs.ScoreDocs.GetEnumerator() 
foreach(var activityDocID in activityDocs.ScoreDocs) 
{ 
    if(dashDocsEnum.Current==null) 
     break; 

    var activityId = GetId(activityDocId.td, "activity_id"); 
    var dashActivityId = GetId(dashDocsEnum.Current.td, "dash_activityid"); 

    if(dashActivityId<activityId) 
    { 
     // spin Dash forward to catch up with Activity 
     while(dashActivityId<activityId) 
     { 
      if(!dashDocsEnum.MoveNext()) 
       break; 
      dashActivityId = GetId(dashDocsEnum.Current.td, "dash_activityid"); 
     } 
    } 

    while(dashActivityId==activityId) 
    { 
     // at this point we have an Activity and a matched Dash 
     var fullActivity = GetActivity(activityDocId.td); 
     var fullDashActivity = GetDash(dashDocsEnum.Current.td); 

     // do something with Activity and Dash 

     if(!dashDocsEnum.MoveNext()) 
      break; 
     dashActivityId = GetId(dashDocsEnum.Current.td, "dash_activityid"); 
    } 
} 

があることを前提とするつもりだプロパティを見て私の頭の上に、それは非常に正しい場合は謝罪します:)

アイデアは、活動をforeachし、活動と同期を維持するためにダッシュ列挙子を前方に歩くことです。ここでは、プロパティ値をStore.YESフィールドに格納することを前提としています。この方法では、一致するものが見つかるまでidのフィールドを取得し、オブジェクト全体を投影します。

別のオプションは、 "文書データストア" としてのLuceneを扱うことです。親子をモデル化するクラスを作成します。そのため、ActivityにはDashのコレクションであるプロパティがあります。

このオブジェクトをバイナリフィールドにシリアル化します。 Store.Noで検索するための適切なフィールドを追加します。これは、結合が必要ないことを意味します。オブジェクト全体を1回のヒットで取得します。

これは、単一のダッシュを追加して結合に頼るのではなく、オブジェクト全体を更新する必要があるため、更新頻度が低い場合に機能します。

幸運:

関連する問題