如何在SolrJ中插入有多个子Bean的Bean对象

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

public  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; } 

有关嵌套文档的插入和搜索,请参阅以下URL:

在Solr(J)中搜索嵌套文档

如果你正在使用Solr6并获得空指针exception,那么请参考: SOLRJ-6.0.0:插入一个bean对象,它将bean对象的列表关联给出空指针exception

但是,如果您尝试插入一个与嵌套bean相关联的bean,那么它将为您提供exception: clazz.getName() + " cannot have more than one Field with child=true"

它将通过下面的DocumentObjectBinder Class of SolrJ代码:

 @SuppressForbidden(reason = "Needs access to possibly private @Field annotated fields/methods") private List collectInfo(Class clazz) { List fields = new ArrayList<>(); Class superClazz = clazz; List 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) () -> { 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; } 
 HttpSolrServer solr = new HttpSolrServer( SOLR_URL ); // Docs to submit Collection batch = new ArrayList(); // 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(); 

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

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