Updating document in solr - solr

I want to update a particular field of a document in solr. However while trying to do so other
fields of the document are becoming null.
CommonsHttpSolrServer server = new CommonsHttpSolrServer("http://mydomain:8983/solr/index_socialmedia/");
List<SolrInputDocument> solrInputDocsList = new ArrayList<SolrInputDocument>();
SolrInputDocument solrInputDoc = new SolrInputDocument();
solrInputDoc.addField("id","427832898745234516478592");
solrInputDoc.addField("city","Kolkata");
solrInputDocsList.add(solrInputDoc);
server.add(solrInputDocsList);
server.commit();
In the above code the "id" field is the unique field.
How can I fix this problem.

I tried with the following code snippet. It's able to do partial update. Try this.
SolrServer server = new HttpSolrServer("http://mydomain:8983/solr/index_socialmedia/");
SolrInputDocument solrInputDoc = new SolrInputDocument();
Map<String, String> update = new HashMap<String, String>();
update.put("set", "Kolkata");
solrInputDoc.addField("id","427832898745234516478592");
solrInputDoc.addField("city", update);
server.commit();

Set <uniqueKey>id</uniqueKey> in your solr schema.xml

Which solr version are you using ?
if it is bellow 4.0 ,solr does not support single field update (partial update)
so in your case existing old document is deleted and new document is inserted with same id
(Reason Solr does not support single field or partial update is lucene does not support partial update )
If you using Solr 4.0 you can refer this solrj api for partial document update

Related

How to specify default search field in SolrJ

I need to specify df parameter in the query. I am using SolrQuery class from SolrJ.
Is there a predefined method to set default search filed in SolrQuery class?
You can try and build the solr query using Solrj as below.
final SolrQuery query = new SolrQuery();
query.setQuery("title:bloomberg");
query.setParam("debugQuery", "on");
query.add("rows", "4");
query.add("rq", "{!ltr reRankDocs=4 model=6029760550880411648}");
query.add("fl", "*,score");
query.add("wt", "json");
query.addFilterQuery("name : tester1");
Also you can use the CommonParams API
solrQuery.setParam(CommonParams.Q, queryString);
solrQuery.setParam(CommonParams.DF, fieldName);
CommonParams Api link

How to update the existing field of solr index using java?

I have a Solr index in a core having 3000 documents.
I want to modify the value of a single field in the entire core based on unique key PaperID.
I'm using the following java code but instead of updating the existing value it adds new documents.
if (solrDocument.get("PaperID").equals(solrDocument2.get("PaperID"))) {
String Mscore = (String) solrDocument.get("ID");
String ModifyScore = (String) solrDocument.get("Author");
//solrDocument.setField("ID", ModifyScore);
//update the field
System.out.println(Mscore);
System.out.println(ModifyScore);
System.out.println(solrDocument2.get("Mscore") + "\n");
SolrInputDocument sid = new SolrInputDocument();
Map<String, Object> fieldModifier = new HashMap<String, Object>(1);
fieldModifier.put("set", ModifyScore);
sid.setField("ID", fieldModifier);
//solr.add(sid);
solr.commit();
}
can anyone guide me accordingly...Best Regards
Your code isn't changing anything, since you've commented out the .add command. And you have to use the actual ID in the ID field, since Solr won't know what document to update otherwise. The field you're changing should have the fieldModifier attached:
SolrInputDocument doc = new SolrInputDocument();
Map<String, String> fieldModifier = new HashMap<String, String>();
// Change ModifyScore to the new value, since you're just using the current value now..
fieldModifier.put("set", ModifyScore);
doc.addField("ID", Mscore);
doc.addField("Author", fieldModifier);
solr.add(doc);
solr.commit();

Solrnet can't get mapping to work

I am using VS2012, .NET 4.5 and SolrNet. I am struggling with solrnet mappings. I've succesfully started Apache Solr with jetty on http://localhost:8983/solr. My class which I want to add to solr is:
public class Register
{
[SolrUniqueKey("id")]
public string Id { get; set; }
[SolrField("body")]
public string Body { get; set; }
}
I succesfully connect to solr, but I can't put my document into it:
Startup.Init<Register>(solrAddress);
Solr = ServiceLocator.Current.GetInstance<ISolrOperations<Register>>();
var reg = new Register
{
Id = "SP2514N",
Body = #"Dosel je prosel"
};
Solr.Add(reg);
Solr.Commit();
Here I receive error, that 'body' is unknown field. I've also used MappingManager, like this:
var mgr = new MappingManager();
var property = typeof(Register).GetProperty("Id");
mgr.Add(property, "id");
mgr.SetUniqueKey(property);
mgr.Add(typeof(Register).GetProperty("Body"), "body");
But, again, my field was not mapped. What am I doing wrong? Isn't the mapping to solr supposed to be done through code? Do I need a special xml file?
You need to confirm that you have a body field defined in your schema. If you are just using the default schema that comes with Solr, it does not include a body field. You can copy an existing similar entry in the schema.xml file, like description to get you going.
For more reference on configuring the Solr schema please refer to the following:
Solr Reference Guide - Overview of Documents, Fields and Schema Design
schema.xml - SolrTutorial.com

Solr, how to use the new field update modes (atomic updates) with SolrJ

Solr 4.x has this nice new feature that lets you specify how, when doing an update on an existing document, the multiValued fields will be updated. Specifically, you can say if the update document will replace the old values of a multivalued field with the new ones, or if it should append the new values to the existing ones.
I've tried this using the request handler, as described here:
http://wiki.apache.org/solr/UpdateXmlMessages#Optional_attributes_for_.22field.22
I've used curl to send xml where some fields used the update=add option:
<field name="skills" update="add">Python</field>
This works as expected.
However I can't get how to do this the Java API (SolrJ).
If I do something like this:
SolrInputDocument doc1 = new SolrInputDocument();
doc1.setField("ID_VENTE", "idv1");
doc1.setField("FACTURES_PRODUIT", "fp_initial");
solrServer.add(doc1);
solrServer.commit();
SolrInputDocument doc2 = new SolrInputDocument();
doc2.setField("ID_VENTE", "idv1");
doc2.setField("FACTURES_PRODUIT", "fp_2");
solrServer.add(doc2);
solrServer.commit();
The value for the field "FACTURES_PRODUIT" becomes "fp_2" (the initial value is lost).
I've also tried:
doc2.addField("FACTURES_PRODUIT", "fp_2");
but the result is the same. I've also looked into the SolrInputField class but haven't found anything similar to this.
So, my question is, how can I use the Solr 4 Java API to updated values into a multiValued field by appening (not replacing) the new values?
Ok, I solved it after debugging a bit the SolrJ code. You have to do this:
SolrInputDocument doc2 = new SolrInputDocument();
Map<String,String> fpValue2 = new HashMap<String, String>();
fpValue2.put("add","fp2");
doc2.setField("FACTURES_PRODUIT", fpValue2);

Limiting terms in Solr's TermsComponent to terms originating from certain documents

I am using Solrs TermsComponent to implement an autocomplete feature. My documents contain tags which I have indexed in a "tags" field. Now I can use TermsComponent to find out which tags are used in all the stored documents. This works pretty well so far.
However there is some additional requirement: Every document has an owner field which contains the ID of the user who owns it. The autocomplete list should only contain tags from documents, that the user who is requesting the autocomplete is actually owning.
I have tried to set the query parameter, however this seems to be ignored by the TermsComponent:
public static List<String> findUniqueTags(String beginningWith, User owner) throws IOException {
SolrParams q = new SolrQuery().setQueryType("/terms")
.setQuery("owner:" + owner.id.toString())
.set(TermsParams.TERMS, true).set(TermsParams.TERMS_FIELD, "tags")
.set(TermsParams.TERMS_LOWER, beginningWith)
.set(TermsParams.TERMS_LOWER_INCLUSIVE, false)
.set(TermsParams.TERMS_PREFIX_STR, beginningWith);
QueryResponse queryResponse;
try {
queryResponse = getSolrServer().query(q);
} catch (SolrServerException e) {
Logger.error(e, "Error when querying server.");
throw new IOException(e);
}
NamedList tags = (NamedList) ((NamedList)queryResponse.getResponse().get("terms")).get("tags");
List<String> result = new ArrayList<String>();
for (Iterator iterator = tags.iterator(); iterator.hasNext();) {
Map.Entry tag = (Map.Entry) iterator.next();
result.add(tag.getKey().toString());
}
return result;
}
So is there a way of limiting the tags returned by TermsComponent, or do I manually have to query all the tags of the user and filter them myself?
According to this and that post on the Solr mailing list, filtering on the terms component is not possible because it operates on raw index data.
Apparently, the Solr developers are working on a real autosuggest component that supports your filtering.
Depending on your requirements you might be able to use the faceting component for autocomplete instead of the terms component. It fully supports filter queries for reducing the set of eligible tags to a subset of the documents in the index.

Resources