如何在SolrNet中对多个表执行索引/搜索

时间:2013-01-02 07:49:27

标签: c# solr solrnet querying

我正在使用SolrNet索引/搜索表集上的数据。

我有两个表类别和项目。

两个表都有相同的字段,因此我有一个基础映射类表单,我派生出来。

[Serializable]
    [XmlRoot(ElementName = "SolrSearchEntity", Namespace = "")]
    [DataContract(Name = "SolrSearchEntity", Namespace = "")]
    public class SolrSearchEntity
    {
        [XmlElement(ElementName = "Id")]
        [DataMember(Name = "Id", IsRequired = true)]
        [SolrUniqueKey("id")]
        public string Id { get; set; }

        [XmlElement(ElementName = "Name")]
        [DataMember(Name = "Name", IsRequired = true)]
        [SolrField("name")]
        public string Name { get; set; }
    }

public class Category : SolrSearchEntity
    {        
    }

    public class Item : SolrSearchEntity
    {
    }

用于索引类别数据的代码块

using (SolrBaseRepository.Instance<Category> repository = new SolrBaseRepository.Instance<Category>())
            {
                var output = ItemStoreDataManager.GetAllCategoryNames(dataAdapter);
                repository.Start();
                var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Category>>();
                solr.AddRange(output);
                solr.Commit();
            }

用于索引项目数据的代码块

using (SolrBaseRepository.Instance<Item> repository = new SolrBaseRepository.Instance<Item>())
                {
                    var output = ItemStoreDataManager.GetAllItemNames(dataAdapter);
                    repository.Start();
                    var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Item>>();
                    solr.AddRange(output);
                    solr.Commit();
                }

我的架构文件

 <fields>
    <!-- declare fields of entity class -->
    <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
    <field name="name" type="text_general" indexed="true" stored="true" omitNorms="true"/>

    <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
    <field name="_version_" type="long" indexed="true" stored="true"/>

  </fields>

查询类别

中的数据
  var entities = ItemStoreManager<Category>.Search(keyword); which will internally execute this.

  new SolrBaseRepository.Instance<T>().Start();
  var solr = ServiceLocator.Current.GetInstance<ISolrOperations<T>>();
  var results = solr.Query(keyword);

奇怪的是,我从 Item 表中获取记录。

我如何告诉SolrNet(搜索引擎)查看我指定的类型。

或者我首先正确编制索引?

请帮忙。

谢谢,

3 个答案:

答案 0 :(得分:1)

当您将数据添加到索引并将数据基于客户端上的已知类型进行查询时,您正在分离数据,而是将它们全部存储在Solr中的相同模式中,并且未指定任何方式来区分项目和类别索尔的记录。我建议你修改你的模式以包含一个类型字段,它只能是一个简单的字符串,如下所示:

 <field name="type" type="string" indexed="true" stored="true" />

然后,您需要将类型字段添加到SolrSearchEntity基类,并在Category和Item类中正确设置它。如下所示:

[Serializable]
[XmlRoot(ElementName = "SolrSearchEntity", Namespace = "")]
[DataContract(Name = "SolrSearchEntity", Namespace = "")]
public class SolrSearchEntity
{
    [XmlElement(ElementName = "Id")]
    [DataMember(Name = "Id", IsRequired = true)]
    [SolrUniqueKey("id")]
    public string Id { get; set; }

    [XmlElement(ElementName = "Name")]
    [DataMember(Name = "Name", IsRequired = true)]
    [SolrField("name")]
    public string Name { get; set; }

    [SolrField("type")]
    public string Type {get; set;}
}

public class Category : SolrSearchEntity
{        
    public Category()
    {
       Type = "Category";
    }
}

public class Item : SolrSearchEntity
{
    public Item()
    {
        Type = "Item";
    }
}

然后当您运行搜索时,如果要按特定类型限制查询,可以添加这样的过滤查询以仅搜索项目:

var entities = ItemStoreManager<Category>.Search(keyword); 
new SolrBaseRepository.Instance<T>().Start();
var solr = ServiceLocator.Current.GetInstance<ISolrOperations<T>>();
var options = new QueryOptions{ 
  FilterQueries = new ISolrQuery[] { new SolrQueryByField("type","Item")}};
var results = solr.Query(keyword, options);

此外,请注意您的id值在数据库中不重叠,因为这将导致您只存储实体的一个实例(类别或项目,无论哪个最后编入索引)。

最后,我觉得您当前的索引策略是合理的,不建议使用DIH。 IMO,您将使用SolrNet客户端库获得更多控制和灵活性。我以前遇到过数据导入处理程序的问题,发现使用SolrNet更容易管理和维护。

答案 1 :(得分:0)

为了从DB索引多个表,我宁愿选择Solr DIH来获得灵活性,而不是任何客户端库。

答案 2 :(得分:0)

除了库克提到的建议外,

在SolrSearchEntity中添加GUID字段

 [XmlElement(ElementName = "UId")]
 [DataMember(Name = "UId", IsRequired = true)]
 [SolrUniqueKey("uid")]
 public Guid UId { get; set; }

在构造函数中初始化Uid

public Item()
{
   Type = "Item";
   UId = Guid.NewGuid();
}

schema.xml中的更改

<fieldType name="uuid" class="solr.UUIDField" indexed="true" />

 <!-- unique field -->
<field name="uid" type="uuid" indexed="true" stored="true" />

<uniqueKey>uid</uniqueKey>

现在索引不会重叠或不一致,搜索范围将缩小到指定的类型。