【问题标题】:How to insert Bean object which has many child Bean in SolrJ如何在 SolrJ 中插入具有许多子 Bean 的 Bean 对象
【发布时间】:2016-10-07 05:57:32
【问题描述】:

我有一个关联配置文件列表和用户 Bean 的 Bean 类活动。现在,如果我试图通过 SOLRJ 在 Solr 中插入这个 Activity bean,它会给我空指针异常。 异常是由以下代码引起的:

public <T> boolean insert (T bean) {
    try {
        UpdateResponse response = solrClient.addBean(bean);
        System.out.println("insert bean ElapsedTime: " + response.getElapsedTime());
        solrClient.commit();
        return true;
    } catch (IOException | SolrServerException e) {
        e.printStackTrace();
    }
    return false;
}

【问题讨论】:

    标签: java solrj solr6


    【解决方案1】:

    如果您使用 Solr6 并获得空指针异常,请参考: SOLRJ-6.0.0: Insertion of a bean object which associate list of bean object is giving null pointer exception

    但是,如果您尝试插入关联嵌套 bean 的 bean,那么它会给您异常:clazz.getName() + " cannot have more than one Field with child=true"

    它将由 SolrJ 的 DocumentObjectBinder 类的以下代码:

    @SuppressForbidden(reason = "Needs access to possibly private @Field annotated fields/methods")
      private List<DocField> collectInfo(Class clazz) {
        List<DocField> fields = new ArrayList<>();
        Class superClazz = clazz;
        List<AccessibleObject> members = new ArrayList<>();
    
        while (superClazz != null && superClazz != Object.class) {
          members.addAll(Arrays.asList(superClazz.getDeclaredFields()));
          members.addAll(Arrays.asList(superClazz.getDeclaredMethods()));
          superClazz = superClazz.getSuperclass();
        }
        boolean childFieldFound = false;
        for (AccessibleObject member : members) {
          if (member.isAnnotationPresent(Field.class)) {
            AccessController.doPrivileged((PrivilegedAction<Void>) () -> { member.setAccessible(true); return null; });
            DocField df = new DocField(member);
            if (df.child != null) {
              if (childFieldFound)
                throw new BindingException(clazz.getName() + " cannot have more than one Field with child=true");
              childFieldFound = true;
            }
            fields.add(df);
          }
        }
        return fields;
      }
    

    【讨论】:

    • 解决办法是什么?是否可以在其他 Bean 中添加不同类型的 Bean 对象作为子文档?
    【解决方案2】:

    嵌套文档插入和搜索请参考下面的 URL:

    Searching for nested Documents in Solr(J)

    【讨论】:

      【解决方案3】:
      HttpSolrServer solr = new HttpSolrServer( SOLR_URL );
      
              // Docs to submit
              Collection<SolrInputDocument> batch = new ArrayList<SolrInputDocument>();
      
              // Parent Doc 1, a person mamed John Jones
              SolrInputDocument person1 = new SolrInputDocument();
              person1.addField( "id",            "john_jones" );
              person1.addField( "content_type",  "person"     );
              // "_t" suffix tells Solr that it's text
              person1.addField( "first_name_t",  "John"       );
              person1.addField( "last_name_t",   "Jones"      );
              // states and history used in edismax examples
              person1.addField( "states_t",      "California Nevada Idaho Maine" );
              person1.addField( "history_t",     "safe accident accident accident accident accident" );
      
              // child docs, the vehicles he owns
              SolrInputDocument p1_car1 = new SolrInputDocument();
              p1_car1.addField( "id",            "jj_car1"    );
              p1_car1.addField( "content_type",  "car"        );
              // For cars "make" is an alias for "manufacturer"
              p1_car1.addField( "make_t",        "Honda"      );
              p1_car1.addField( "model_t",       "Accord"     );
      
              SolrInputDocument p1_car2 = new SolrInputDocument();
              p1_car2.addField( "id",            "jj_car2"    );
              p1_car2.addField( "content_type",  "car"        );
              p1_car2.addField( "make_t",        "Nissan"     );
              p1_car2.addField( "model_t",       "Maxima"     );
      
              SolrInputDocument p1_bike1 = new SolrInputDocument();
              p1_bike1.addField( "id",           "jj_bike1"   );
              p1_bike1.addField( "content_type", "bike"       );
              p1_bike1.addField( "make_t",       "Yamaha"     );
              p1_bike1.addField( "model_t",      "Passion"    );
      
              SolrInputDocument p1_bike2 = new SolrInputDocument();
              p1_bike2.addField( "id",           "jj_bike2"   );
              p1_bike2.addField( "content_type", "bike"       );
              p1_bike2.addField( "make_t",       "Peugeot"    );
              p1_bike2.addField( "model_t",      "Vivacity"   );
      
              // Add children to parent
              person1.addChildDocument( p1_car1  );
              person1.addChildDocument( p1_car2  );
              person1.addChildDocument( p1_bike1 );
              person1.addChildDocument( p1_bike2 );
      
              // Add parent to batch
              batch.add( person1 );
      
      
              // Parent Doc 2, person mamed Satish Smith
              SolrInputDocument person2 = new SolrInputDocument();
              person2.addField( "id",           "satish_smith" );
              person2.addField( "content_type", "person"       );
              person2.addField( "first_name_t", "Satish"       );
              person2.addField( "last_name_t",  "Smith"        );
              person2.addField( "states_t",     "California Texas California Maine Vermont Connecticut" );
              person2.addField( "history_t",    "safe safe safe safe safe safe safe safe accident" );
      
              // Vehicles (child docs)
              SolrInputDocument p2_car1 = new SolrInputDocument();
              p2_car1.addField( "id",            "ss_car1"     );
              p2_car1.addField( "content_type",  "car"         );
              p2_car1.addField( "make_t",        "Peugeot"     );
              p2_car1.addField( "model_t",       "iOn"         );
              SolrInputDocument p2_bike1 = new SolrInputDocument();
              p2_bike1.addField( "id",           "ss_bike1"    );
              p2_bike1.addField( "content_type", "bike"        );
              p2_bike1.addField( "make_t",       "Honda"       );
              p2_bike1.addField( "model_t",      "Spree"       );
              // link objects and add to batch
              person2.addChildDocument( p2_car1  );
              person2.addChildDocument( p2_bike1 );
              batch.add( person2 );
      
              System.out.println( "Adding batch of " + batch.size() + " parent docs" );
      
              // Submit as a group
              solr.add( batch );
              solr.commit();
      

      【讨论】:

      【解决方案4】:

      通过使用 SolrInputDocument 类,我可以插入包含多个嵌套文档的文档,甚至 addBeans 方法(在 SolrJ 代码下方)也可以这样做。所以我应该为每个 bean 构建 SolrInputDocument 对象以进行索引。这是唯一的解决方案吗?

           public UpdateResponse addBeans(String collection, Collection<?> beans, int commitWithinMs) throws SolrServerException, IOException {
          DocumentObjectBinder binder = this.getBinder();
          ArrayList<SolrInputDocument> docs =  new ArrayList<>(beans.size());
          for (Object bean : beans) {
            docs.add(binder.toSolrInputDocument(bean));
          }
          return add(collection, docs, commitWithinMs);
        }
      

      【讨论】:

        猜你喜欢
        • 2016-09-11
        • 1970-01-01
        • 2013-06-22
        • 2014-07-17
        • 2013-02-18
        • 1970-01-01
        • 1970-01-01
        • 2019-06-12
        • 2019-04-19
        相关资源
        最近更新 更多