2016-05-17 138 views
1

我在我的项目中使用Lucene.NET。现在我有一个棘手的星座。我有两个实体:搜索两个Lucene文档

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; } 
} 

我存储实体活动的文件和短跑作为Lucene的指数文档。现在

,我可以搜索短跑条目类似

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

或活动条目类似

+Subject:"Appointment-Invitation" 

现在,我必须在两个文档中搜索短跑条目。例如,我必须搜索所有具有用户名“mm”的短划线条目,并在描述中包含字符串“约会”,或者相关活动实体在主题中具有“约会”。在SQL(伪)这将是:

... 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语句。 – Eser

回答

0

把不同的实体类型到同一指数

当你要小心如果你搜索“ID:1”你怎么知道你是否已经检索破折号或活动?

或者:

  • 确保字段名是唯一的,即 “dash_id”, “ACTIVITY_ID”
  • 添加一个 “_type” 字段并添加 “_type:破折号” 或 “_type:活动” 作为过滤器到搜索

你不能做你在一个单一的查询至少与目前Lucene.net“加入”(3.0.3)

Lucene是文档数据存储就像一个键值存储一样。每个文档都是“只是一堆领域”。

您可以查询每个实体,然后使用Linq加入两个集合。但是这可能效率很低并且内存密集。全部取决于你期望得到多少结果。如果数字很低,那么这可能是最简单的。

但是,你可以做一些相当不错的事情,有两个查询和一个“同步可枚举”。警告:这很难说什么是“短跑”信息,但看我要去的属性假设有许多短跑每个活动

伪代码

// 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添加适当的搜索字段。这意味着不需要连接,你可以在一次打击中获得整个对象。

这适用于更新频率较低的情况,因为您需要更新整个对象而不是仅添加一个Dash并依赖联接。

祝你好运:)