如何在 SolrJ 中插入具有多个子 Bean 的 Bean 对象
How to insert Bean object which has many child Bean in SolrJ
我有一个 Bean Class Activity,它将配置文件列表和一个用户 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;
}
通过使用 SolrInputDocument class 我能够插入包含多个嵌套文档的文档,甚至 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);
}
如果您使用的是 Solr6 并出现空指针异常,请参考:
但是,如果您尝试插入一个关联嵌套 bean 的 bean,那么它会给您一个例外:clazz.getName() + " cannot have more than one Field with child=true"
将由SolrJ的DocumentObjectBinderClass下面的一段代码:
@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;
}
嵌套文档插入和搜索参考下面URL:
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();
我有一个 Bean Class Activity,它将配置文件列表和一个用户 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;
}
通过使用 SolrInputDocument class 我能够插入包含多个嵌套文档的文档,甚至 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);
}
如果您使用的是 Solr6 并出现空指针异常,请参考:
但是,如果您尝试插入一个关联嵌套 bean 的 bean,那么它会给您一个例外:clazz.getName() + " cannot have more than one Field with child=true"
将由SolrJ的DocumentObjectBinderClass下面的一段代码:
@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;
}
嵌套文档插入和搜索参考下面URL:
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();