【问题标题】:Solr Indexing SQL record with duplicate uniqueKey具有重复唯一键的 Solr 索引 SQL 记录
【发布时间】:2013-11-09 19:01:42
【问题描述】:

我们需要对具有数百万条记录(音乐元数据)的数据库进行全文搜索,而我在 Solr 上工作了大约 2 周,我需要一些关于索引的帮助。我正在使用DataImportHandler 并有生成如下结果的 SQL 查询:

正如您在上图中所见,id(整数数据类型)在 SQL 结果中重复,也用于DIH,当我将 uniqueKey 设置为 <uniqueKey>id</uniqueKey> 时,solr 会覆盖仅留下的值一个记录/行,事实上我认为最后一个处理的是countryCode'TL'。

当我第一次遇到这个问题时,我知道为什么 solr 会覆盖该值,这是正常的,所以我想为 db 中的每条记录添加一个全局标识符,一个 guid - 没有正确考虑,我最终得到了相同的重复如您所见,charGuid 是来自 MySQL 的 uuid() 重复。

但是当我使用charGuid(字符串数据类型)作为<uniqueKey>charGuid</uniqueKey> 的唯一键时,我得到了所有记录的索引,并且没有任何内容被覆盖,但当然重复是不可避免的。我在这里看到的问题是,当我必须进行增量更新时,solr 将无法确切知道要更新哪个文档,事实上,来自管理控制台的快速测试显示,最后或第一个记录它的发现唯一键已更新。 - 这是不可接受的。

我偶然发现了一篇引用 multiValued="true" 的文章,我认为在我的 SQL 中创建代表 JOIN 列的字段可以解决问题,但事实并非如此。我希望 id:10 的记录将返回 countryCode 列表,但没有。

我只是对如何规避这个问题以及为什么我没有发现某人发布的类似问题感到困惑。

如果我没有得到有意义的答案,我想我将不得不使用charGuid 作为允许重复的<uniqueKey>,然后使用Solr Document Deduplication Detection 来处理我的索引的更新,但我想相信,有更好的方法。

更新 这是我的 data-config.xml 和 schema.xml 定义:

<entity name="albums" query="select * from Album">
            <entity name="track" query="select t.id as id, t.title as trackTitle, t.removed as trackRemovedDate, t.productState from Track t  where t.albumId='${albums.id}'"/>         
            <entity name="albumSalesAreaId" query="select asa.salesAreaId as albumSalesAreaId  from AlbumSalesArea asa where asa.albumId='${albums.id}'"/>
            <entity name="albumSalesArea" query="select sa.name as albumSalesArea from SalesArea sa where sa.id='${albumSalesAreaId.salesAreaId}'"/>            
            <entity name="salesAreaCountry" query="select sac.countryId as 'salesAreaCountry' from SalesAreaCountry sac where sac.salesAreaId ='${salesArea.id}'"/>
            <entity name="countryId" query="select c.id as 'countryId' from Country c where c.id = '${salesAreaCountry.countryId}'"/>
            <entity name="countryName" query="select c.name as 'countryName' from Country c where c.id = '${salesAreaCountry.countryId}'"/>                         
        </entity>

**Schema.xml**
<!--new multivalue fields -->
<field name="albumSalesArea" type="int" stored="true" indexed="true" multiValued="true"/>
<field name="albumSalesAreaId" type="int" indexed="true" stored="true" multiValued="true"/>
<field name="salesAreaCountry" type="int" stored="true" indexed="true" multiValued="true"/>
<field name="countryId" type="int" indexed="true" stored="true" multiValued="true"/>
<field name="countryName" type="text_general" indexed="true" stored="true" multiValued="true"/>

当我将我的 solr 响应与 SQL 结果进行比较时,我看到 countryCode 但 solr 没有,只​​返回

"albumSalesAreaId": [
          1,
          3
        ],

不知道为什么国家等没有出现。

更新 2

data-config.xml

<document name="content">
        <entity name="albums" query="select * from Album">          
            <entity name="tracks" query="select t.id, t.title, t.removed, t.productState from Track t  where t.albumId='${albums.id}'">         
                <field column="id" name="id" />
                <field column="title" name="trackTitle" />
                <field column="removed" name="trackRemovedDate" />
                <field column="productState" name="trackProductState" />
            </entity>           
            <entity name="albumSalesAreaIds" query="select salesAreaId  from AlbumSalesArea  where albumId = '${albums.id}'">               
                <field column="salesAreaId" name="albumSalesAreaId"/>
            </entity>
            <entity name="albumSalesAreaNames" query="select name  from SalesArea  where id = '${albumSalesAreaIds.salesAreaId}'">
                <field column="name" name="albumSalesArea"/>
            </entity>               
            <entity name="salesAreaCountryIds" query="select countryId from SalesAreaCountry where salesAreaId ='${albumSalesAreaIds.salesAreaId}'">                    
                <field column="countryId" name="countryId" />
            </entity>   
            <entity name="salesAreaCountry" query="select name from Country where id ='${salesAreaCountryIds.countryId}'">                      
                <field column="name" name="countryName" />
            </entity>
            <field column="title" name="albumTitle"/>   
            <field column="removed" name="albumRemovedDate"/>  
            <field column="productState" name="albumProductState" />            
        </entity>   
    </document>

schema.xml

<field name="catchall" type="text_general" stored="true" indexed="true" multiValued="true"/>      
<field name="publisher" type="text_general" indexed="true" stored="true"/>  
<field name="uuid" type="binary" indexed="false" stored="true"/>
<field name="trackRemovedDate" type="tdate" indexed="true" stored="true"/>
<field name="albumRemovedDate" type="tdate" indexed="true" stored="true"/>
<field name="trackProductState" type="int" indexed="true" stored="true"/>
<field name="albumProductState" type="int" indexed="true" stored="true"/>
<field name="countryCode" type="text_general" indexed="true" stored="true" multiValued="true"/> 
<field name="albumTitle" type="text_general" indexed="true" stored="true"/>
<field name="trackTitle" type="text_general" indexed="true" stored="true" multiValued="true"/>
<field name="guid" type="text_general" indexed="true" stored="true"/>
<!--new multivalue fields -->
<field name="albumSalesAreaId" type="int" indexed="true" stored="true" multiValued="true"/>
<field name="salesAreaCountry" type="int" stored="true" indexed="true" multiValued="true"/>
<field name="countryId" type="int" indexed="true" stored="true" multiValued="true"/>
<field name="countryName" type="text_general" indexed="true" stored="true" multiValued="true"/>
<field name="albumSalesArea" type="text_general" indexed="true" stored="true" multiValued="true"/>

id:5 的示例 solr 响应

{
  "responseHeader": {
    "status": 0,
    "QTime": 1,
    "params": {
      "indent": "true",
      "q": "id:5",
      "_": "1383221233535",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 1,
    "start": 0,
    "docs": [
      {
        "id": "5",
        "catchall": [
          "5",
          "Test Album 5",
          "2011-10-21 00:00:00.0",
          "[B@261ca3cb",
          "Test Track 1",
          "Ya man 2",
          "2011-10-17 16:21:29.0",
          "1",
          "1450412569164513280"
        ],
        "albumTitle": "Test Album 5",
        "albumRemovedDate": "2011-10-21T00:00:00Z",
        "uuid": "6oT/MMl+RDaPyKpGK1KN0w==",
        "trackTitle": [
          "Test Track 1",
          "Ya man 2"
        ],
        "trackRemovedDate": "2011-10-17T16:21:29Z",
        "albumSalesAreaId": [
          1
        ],
        "_version_": 1450412569164513300
      }
    ]
  }
}

id:5 的 SQL 结果

trackTitle 和 albumSalesAreaId 似乎是正确的,但不确定为什么其他人没有被包括在内,但是如果用from SalesArea where id = 1 硬编码albumSalesAreaNames 实体,那么我会将albumSalesArea 字段添加到结果中,所以看起来像 from SalesArea where id = '${albumSalesAreaIds.salesAreaId}'" 正在返回 null,之前也通过 'IN' 测试确认。

【问题讨论】:

    标签: solr lucene full-text-search solr4


    【解决方案1】:

    这看起来确实是一个简单地用多值字段解决的问题。 如果您在此结构中使用多值字段,您将获得一个 ID=10 的文档,所有重复值将只存在一次,所有其他字段将是多值的。例如,NAME 字段将包含 4 个不同的国家和国家代码。

    查看这篇文章,了解如何构建您的 dataimportHandler 以实现此目的:

    http://wiki.apache.org/solr/DataImportHandler#Full_Import_Example

    基本上每个多值字段都需要一个查询:

    <dataConfig>
    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />
    <document name="products">
        <entity name="item" query="select * from item">
            <field column="ID" name="id" />
            <field column="code" name="code" />
    
            <entity name="countryName" query="select name from countrytable where item_id='${item.ID}'">
                <field name="name" column="description" />
            </entity>
            <entity name="countryCode" query="select countryCode from countrytable where item_id='${item.ID}'">              
            </entity>
        </entity>
    </document>
    

    【讨论】:

    • 这是我偶然发现上面提到的 multivalue=true 文章时所设想的,我会做更多的挖掘,肯定会回来报告结果,谢谢你至少给了我一些小费。干杯
    • 我不确定如何在 SQL 查询中使该字段成为多值,我尝试选择 entity.id、entity2.*、entity3.* 等,我无法为这些选定的字段/列指定别名到 macth 字段名,所以我不确定如何在 schema.xml 中将字段映射为多值。我是否正确地说 select coulmns 不能是字段,例如 entity2.id, enity2.name ?因此我选择了 entity2.*, entity3.* ...
    • 检查更新的答案。我添加了一个例子。你必须做很多查询
    • 我认为您在查询中使用了错误的字段名称。您编写“select asa.salesAreaId as albumSalesAreaId”,因此该字段现在称为“albumSalesAreaId”,但您在下一个查询中使用旧字段名称:“${albumSalesAreaId.salesAreaId}”。用“${albumSalesAreaId.albumSalesAreaId}”更改它
    • 您可以更新答案中的架构吗?我不认为你应该使用 IN。您是否先尝试使用“=”进行正常查询?
    【解决方案2】:

    (代表 OP 发布)。

    解决方案

        <entity name="albumSalesAreaNames" query="select name  from SalesArea  where id = '${albumSalesAreaIds.salesAreaId}'">
            <field column="name" name="albumSalesArea"/>
        </entity>
        <field column="salesAreaId" name="albumSalesAreaId"/>
        </entity>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      相关资源
      最近更新 更多