我在我的项目中使用Lucene.NET。现在我有一个棘手的星座。我有两个实体:
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; }
}
我将实体活动存储为文档,并将Dash作为文档存储在Lucene-Index中。
现在,我可以搜索像
这样的Dash-Entries+Description:"Appointment" +Username:"mm"
或
之类的活动条目+Subject:"Appointment-Invitation"
现在,我必须在两个文档上搜索Dash-Entries。例如,我必须搜索用户名" mm"的所有Dash条目。并有字符串"约会"在描述或相关的活动实体中有"约会"在主题中。在SQL(Pseudo)中,这将是:
... where Dash.UserName = 'mm' and (Dash.Description like 'Appointment%' or Dash.Activity.Subject like 'Appointment%'
有人可以帮助我,我怎么能用Lucene.NET做到这一点?也许我必须以另一种方式将文档存储在Lucene.NET-Index中?
答案 0 :(得分:0)
将不同的实体类型放入同一个索引时应该注意
如果你搜索“id:1”,你怎么知道你是否检索过Dash或者一个活动?
或者:
您无法在单个查询中“加入”至少使用当前的Lucene.net(3.0.3)
Lucene是一个文档数据存储区,它有点像键值存储。每个文档都“只是一堆字段”。
您可以只查询每个实体,然后使用Linq加入这两个集合。但这可能是非常低效和内存密集的。一切都取决于您期望的结果数量。如果数字很低,那么这可能是最简单的。
但是,您可以通过两个查询和“同步可枚举”来做一些相当不错的事情。警告:很难说“Dash”是什么,但是看看属性我将假设每个Activity都有很多Dash
伪代码
// 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");
}
}
这只是写在我的头顶,所以道歉,如果它不太正确:))
这个想法是预先进行活动,然后向前推进破折号枚举器以与活动保持同步。假设您将属性值存储在Store.YES
字段中。这种方法只获取id
字段,直到找到匹配项,然后投影整个对象。
另一个选项
将Lucene视为“文档数据存储区”。创建一个为父子建模的类。所以Activity有一个属性,它是Dash的集合。
将该对象序列化为二进制字段。添加适当的字段以便使用Store.No
进行搜索。这意味着不需要连接,只需一次点击即可获得整个对象。
如果您需要更新整个对象而不是仅添加单个Dash并依赖于连接,则更新频率较低时,此方法有效。
祝你好运:)