Solr索引具有重复uniqueKey的SQL记录

时间:2013-10-30 09:23:17

标签: solr lucene full-text-search solr4

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

enter image description here

正如您在上面的附图中所看到的,id(整数数据类型)在DIH中使用的SQL结果中重复,当我将uniqueKey设置为<uniqueKey>id</uniqueKey>时solr覆盖了只留下一个记录/行的值,实际上我认为最后一个处理的是countryCode'TL'的那个。

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

但是当我使用charGuid(字符串数据类型)作为<uniqueKey>charGuid</uniqueKey>的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

数据-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"/>

示例solr响应为id:5

{
  "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结果

enter image description here

trackTitlealbumSalesAreaId似乎是正确的,但不确定为什么其他人没有被包括在内,但如果albumSalesAreaNames entiy与from SalesArea where id = 1进行硬编码,那么我得{{1} }}字段已添加到结果中,因此似乎albumSalesArea from SalesArea返回null,也是先前通过'IN'测试确认的。

2 个答案:

答案 0 :(得分:1)

这看起来真的是一个用多值字段解决的问题。 如果在此结构中使用多值字段,则将获得一个ID = 10的文档,所有重复的值将只存在一次,所有其他字段将是多值的。例如,NAME字段将包含4个不同的国家/地区,因此包含country_code。

看看这篇关于如何构建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>

答案 1 :(得分:0)

(代表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>