Solr 不会覆盖 - 重复的 uniqueKey 条目

Posted

技术标签:

【中文标题】Solr 不会覆盖 - 重复的 uniqueKey 条目【英文标题】:Solr doesn't overwrite - duplicated uniqueKey entries 【发布时间】:2016-03-19 02:46:56 【问题描述】:

我对 Solr 5.3.1 有疑问。我的架构相当简单。我有一个 uniqueKey,它是字符串的“id”。索引,存储和必需,非多值。

我首先添加带有“content_type:document_unfinished”的文档,然后覆盖相同的文档,具有相同的 id 但另一个 content_type:document。然后该文档在索引中出现两次。同样,唯一的唯一键是“id”,作为字符串。 id 最初来自 mysql-index 主 int。

看起来这种情况不止一次:

http://lucene.472066.n3.nabble.com/uniqueKey-not-enforced-td4015086.html

http://lucene.472066.n3.nabble.com/Duplicate-Unique-Key-td4129651.html

就我而言,并非索引中的所有文档都是重复的,只是一些。我假设 - 最初 - 当索引中存在相同的 uniqueKey 时,它们会在提交时被覆盖。这似乎不像我预期的那样工作。我不想简单地更新文档中的某些字段,我想用所有子项完全替换它。

一些统计数据:索引中有大约 350k 个文档。主要是 childDocuments。文档由“content_type”字段区分。我使用 SolrJ 以这种方式导入它们:

HttpSolrServer server = new HttpSolrServer(url);
server.add(a Collection<SolrInputDocument>);
server.commit();

我总是再次与所有孩子一起添加整个文档。它没有什么过于花哨的。我最终得到了相同 uniqueKey 的重复文档。没有侧面注射。我只使用集成的 Jetty 运行 Solr。我没有“手动”在 java 中打开 lucene 索引。

然后我所做的是再次删除+插入。这似乎工作了一段时间,但在某些情况下开始出现此错误消息:

父查询产生的文档与父过滤器不匹配

发生这种情况的文档似乎是完全随机的,似乎只有一件事出现:它发生的地方是一个 childDocument。我没有运行什么特别的东西,基本上是从网站上下载了solr包并用bin/solr start运行它

有人有什么想法吗?

编辑 1

我想我找到了问题,这似乎是一个错误?重现问题:

我在 virtualBox 中将 Solr 5.3.1 下载到 Debian 并使用 bin/solr start 启动它。添加了具有基本配置集的新核心。基本配置集没有任何变化,只是将其复制并添加了核心。

这导致两个文档在索引中具有相同的 id:

    SolrClient solrClient = new HttpSolrClient("http://192.168.56.102:8983/solr/test1");
    SolrInputDocument inputDocument = new SolrInputDocument();
    inputDocument.setField("id", "1");
    inputDocument.setField("content_type_s", "doc_unfinished");
    solrClient.add(inputDocument);
    solrClient.commit();
    solrClient.close();

    solrClient = new HttpSolrClient("http://192.168.56.102:8983/solr/test1");
    inputDocument = new SolrInputDocument();
    inputDocument.setField("id", "1");
    inputDocument.setField("content_type_s", "doc");
    SolrInputDocument childDocument = new SolrInputDocument();
    childDocument.setField("id","1-1");
    childDocument.setField("content_type_s", "subdoc");
    inputDocument.addChildDocument(childDocument);
    solrClient.add(inputDocument);
    solrClient.commit();
    solrClient.close();

搜索:

http://192.168.56.102:8983/solr/test1/select?q=%3A&wt=json&indent=true

导致以下输出:



  "responseHeader": 
    "status": 0,
    "QTime": 0,
    "params": 
      "q": "*:*",
      "indent": "true",
      "wt": "json",
      "_": "1450078098465"
    
  ,
  "response": 
    "numFound": 3,
    "start": 0,
    "docs": [
      
        "id": "1",
        "content_type_s": "doc_unfinished",
        "_version_": 1520517084715417600
      ,
      
        "id": "1-1",
        "content_type_s": "subdoc"
      ,
      
        "id": "1",
        "content_type_s": "doc",
        "_version_": 1520517084838101000
      
    ]
  

我做错了什么?

【问题讨论】:

我目前面临的情况似乎与您的情况非常相似:我也使用 SolrJ,我也使用 childDocuments,而且我最近也刚刚检测到,在文档的普通更新中,之后该文档在索引中存在两次,具有相同的唯一键。我还想我可以尝试通过 solrClient.deleteById(id) 显式删除文档,这似乎可以解决问题 - 但是,由于您声明这不是真正的修复,我仍然担心。 我编写了一个小型 Java 测试应用程序,它会生成您所描述的问题。可以在这里找到:github.com/sebastianriemer/SolrDuplicateTest 我很想知道你是否得到和我一样的结果。我还写信给 solr-user 邮件列表,并将答案发回这里。 我想我在某处读到 Solr 处理带有子文档的文档与没有子文档的文档不同。我不记得我在哪里阅读它,但我立即开始添加子文档,从第一个文档开始。从那以后,覆盖对我来说是有效的——但我仍然认为它是 Solr 的一个“错误”,它没有将唯一键......视为......好吧......独一无二。我每天都会在索引中添加几个 10k 文档,并且它可以正常工作。 顺便说一句,我建议用你的解决方案写一个你自己问题的答案并接受它。据我所知,这被认为是一种很好的做法,可以帮助遇到同样问题的其他人。 【参考方案1】:

感谢您的反馈!我写这个作为答案,因为否则它太长了。实际上,我从邮件列表中得到了相同的回复:

米哈伊尔·赫鲁德涅夫 你好塞巴斯蒂安,

混合独立的文档和块不起作用。有很多 未解决的问题。

2016 年 3 月 9 日星期三下午 3:02,塞巴斯蒂安·里默 写道:

嗨,

简短地描述我的问题,而不仅仅是链接到 测试应用程序,使用 SolrJ 我执行以下操作:

1) 创建一个新文档作为父文档并提交

    SolrInputDocument parentDoc = new SolrInputDocument();
    parentDoc.addField("id", "parent_1");
    parentDoc.addField("name_s", "Sarah Connor");
    parentDoc.addField("blockJoinId", "1");
    solrClient.add(parentDoc);
    solrClient.commit();

2) 创建一个具有与 1) 中相同的唯一 ID 的新文档,其中包含一个孩子 附加文件

    SolrInputDocument parentDocUpdateing = new SolrInputDocument();
    parentDocUpdateing.addField("id", "parent_1");
    parentDocUpdateing.addField("name_s", "Sarah Connor");
    parentDocUpdateing.addField("blockJoinId", "1");

    SolrInputDocument childDoc = new SolrInputDocument();
    childDoc.addField("id", "child_1");
    childDoc.addField("name_s", "John Connor");
    childDoc.addField("blockJoinId", "1");

    parentDocUpdateing.addChildDocument(childDoc);
    solrClient.add(parentDocUpdateing);
    solrClient.commit();

3) 在 solr 索引中生成 2 个 id="parent_1" 的文档

这是正常行为吗?我认为现有的文件应该是 更新而不是生成具有相同 id 的新文档。

有关完整的工作测试应用程序,请参阅原始消息。

最好的问候, 塞巴斯蒂安

我认为这是一个已知问题,并且存在一些与此相关的票证,但我很高兴有办法处理它(从头开始添加子文档)(https://issues.apache.org/jira/browse/SOLR-6096, https://issues.apache.org/jira/browse/SOLR-5211, https://issues.apache.org/jira/browse/SOLR-7606)

【讨论】:

感谢您总结了这个问题。我不确定这是否真的是一个解决方案。它只是让我想起了一个非常糟糕的解决方法。无论如何,我会接受作为一个答案,即使是强硬的我对这种行为也不是很满意。有点失望,它没有在 solr 文档中以粗体红色字母提及......

以上是关于Solr 不会覆盖 - 重复的 uniqueKey 条目的主要内容,如果未能解决你的问题,请参考以下文章

solr 的基本使用

solrcloud 在windows可以集群吗

不是抽象的,也不会覆盖抽象方法[重复]

“方法不会覆盖其超类中的任何方法”Swift 3 [重复]

方法不会覆盖其超类 swift 3.0 错误中的任何方法 [重复]

为 jdbc 数据直接 sqlserver 驱动程序覆盖 org.apache.solr.handler.dataimport.JdbcDataSource