solr-4.9.0: how can solrj delete documents in "implicit router" effectively? - router

I used "implicit router" when created my collection and I used SolrJ to access Solr. In this mode, I do my query request by providing a param named route。But, if I want to call CloudSolrServer's deleteByQuery() method,how can I set this parameter? I just only want to pass my request to the right shard, not all shards, I don't know how to get it。

Luckily,I have founded the answer. When I was reading CloudSolrServer's source code, I founded the following method:
public UpdateResponse deleteByQuery(String query) throws SolrServerException, IOException {
return new UpdateRequest().deleteByQuery( query ).process( this );
}
And the UpdateResponse class has a method setParam().
So, the final code is as follows:
UpdateRequest deleteRequest = new UpdateRequest();
deleteRequest.setParam("_route_", shardId);
UpdateResponse reponse = deleteRequest.deleteByQuery(delQuery).process(cloudSolrServer_);
I have tried it and found no problems.

Related

Getting method name related to a rest service

I wanted to know if there exist a way of retrieving the actual method name associated to a rest service provided. Lets suppose my url is http://localhost:8080/v1/mytesturl now i want to retrieve the actual method name that is associated with this url.
Actually we are maintaining some key/value pair specific to the method that we have created and i need to make some checks based on the method name that gets executed using these values.
Plz let me know if there exist some way to do that..
Simply get the method name from the Object class.
#RestController
#RequestMapping("")
public class HomeController {
#RequestMapping("/mytesturl")
#ResponseBody
public String getMethodName() {
return new Object(){}.getClass().getEnclosingMethod().getName();
}
}
i got the solution by using this
Map<RequestMappingInfo, HandlerMethod> handlerMethods = RequestMappingHandlerMapping.getHandlerMethods();
HandlerExecutionChain handler = RequestMappingHandlerMapping.getHandler(requestr);
HandlerMethod handler1 = null;
if(Objects.nonNull(handler)){
handler1 = (HandlerMethod) handler.getHandler();
handler1.getMethod().getName()
}
this provide me with what i wanted..

How to Add a reference between two BsonDocuments using MongoDbClient in C#

I'm trying to add a reference between two BsonDocument in C#, but unfortunately, I don't know and haven't found any documentation that explains how to do it.
Here is my code:
var parent = new BsonDocument( new BsonElement("name","parentTest"));
parent.Add("newField", "test");
var child1 = new BsonDocument( new BsonElement("name","childTest1"));
var child2 = new BsonDocument( new BsonElement("name","childTest2"));
I want to create a reference (one to many) between the parent BsonDocument and the two child documents (child1 and child2).
I have tried to use MongoDbRef, but without success.
Thank you
After reading a lot of documents about the csharp provider without any lead, I have decided to read the php documentation and to follow the following steps:
To create the documents and the reference using the mongodb command
line client
Query the database using the csharp provider and see what kind
of type the BsonDocument will return in the reference values.
Recreate the same structure and see if the command line client
will return the same json string.
I don't know is the official cshap provider have something that performs this for me, but I was unable to find any document explaining how to do it. So I have solved this question by myself. If someone knows an different or easier way to do it, please share your knowlegde here. Thank you all!
As result of my effort, I've created an extension method to make it easier. The code below is such class:
public static class MyMongoDbExtension
{
public static BsonDocument GetDBRef(this BsonDocument document, string collectionName)
{
var id = document.GetValue("_id");
var result = new BsonDocument();
result.Add(new BsonElement("$ref", collectionName));
result.Add(new BsonElement("$id", id));
return result;
}
}

Spring MVC REST using #RequestBody List<?> returns HTTP 400 syntactically incorrect

I am using Spring 4 + Jackson 2 and have written a fully functional POST method using #RequestBody on a custom class. This method has no trouble unmarshalling the object.
#ResponseBody
#RequestMapping(value="store", method = RequestMethod.POST)
public ServiceResponse store(#RequestBody CustomClass list) {
...
}
// Request: { code: "A", amount: 200 }
When I attempted to add another method to handle a collection of the same class instead, my POST requests were returning with the following error.
HTTP Status 400: The request sent by the client was syntactically incorrect.
I note that this error typically occurs when the JSON submitted does not match the entity class. However, all I am doing is submitting an array of the same object instead of the object itself, which has already proven to work.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody List<CustomClass> list) {
...
}
// Request: [{ code: "A", amount: 200 }, { code: "B", amount: 400 }]
Am I missing something here?
In Java, type information for generics is erased at runtime, so Spring sees your List<CustomClass> object as List<Object> object, thus it cannot understand how to parse it.
One of ways to solve it, you could capture the type information by creating a wrapper class for your list, like this:
public class CustomClassList extends ArrayList<CustomClass> {
}
Sergey is right that the issue is due to type erasure. Your easiest way out is to bind to an array, so
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody CustomClass[] object) {
...
}
The answer is that Spring 4 doesn't actually get rid of type erasure, contrary to what some other solutions suggest. While experimenting on debugging via manual unmarshalling, I decided to just handle that step myself instead of an implicit cast that I have no control over. I do hope someone comes along and proves me wrong, demonstrating a more intuitive solution though.
#ResponseBody
#RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(#RequestBody String json) {
try {
List<CustomClass> list = new ObjectMapper().readValue(json, new TypeReference<List<CustomClass>>() { });
...
} catch (Exception e) {
...
}
}
Bonus: Right after I got this working, I bumped into this exception:
IllegalStateException: Already had POJO for id
If anyone gets this, it's because the objects in the list happen to reference some object that another item in the list already references. I could work around this since that object was identical for my entire collection, so I just removed the reference from the JSON side from all but the first object. I then added the missing references back after the JSON was unmarshalled into the List object.
Two-liner for the Java 8 users (the User object reference was the issue in my case):
User user = list.get(0).getUser();
list.stream().filter(c -> c.getUser() == null).forEach(t -> t.setUser(user));

Spring MVC REST

I'm using Spring MVC and I have a controller mapped to a url lets call it example. I also have a method called show that allows me to view one of my examples based on an id.
#RequestMapping("/example")
#RequestMapping(value = "/{id}", produces = "text/html")
public String show(#PathVariable("id") String id, Model model) {
//Do some stuff and return a view
}
The problem is that the id is a URI and it has forward slashes. (e.g. test/case/version/sample might be an id so the resulting url is example/test/case/version/sample) so as a result my application gives me an error "Requested resource not found". I can't easily change the format of these ids. It's a list given to me that I have to work with. Is there a way around this? Thanks in Advance.
You can try using Regular expressions on the #PathVariable.
Like this from the Spring Docs:
#RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
public void handle(#PathVariable String version, #PathVariable String extension) {
// ...
}
}
You'll just have to think on a regular expression that matches the "example/test/case/version/sample" that is your expression.
See the title: "URI Template Patterns with Regular Expressions"
on this page: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html for more information

Use GuidRepresentation.Standard with MongoDB

I am implementing a custom IBsonSerializer with the official MongoDB driver (C#). I am in the situation where I must serialize and deserialize a Guid.
If I implement the Serialize method as follow, it works:
public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
BsonBinaryData data = new BsonBinaryData(value, GuidRepresentation.CSharpLegacy);
bsonWriter.WriteBinaryData(data);
}
However I don't want the Guid representation to be CSharpLegacy, I want to use the standard representation. But if I change the Guid representation in that code, I get the following error:
MongoDB.Bson.BsonSerializationException: The GuidRepresentation for the writer is CSharpLegacy, which requires the subType argument to be UuidLegacy, not UuidStandard.
How do I serialize a Guid value using the standard representation?
Old question but in case someone finds it on google like I did...
Do this once:
BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;
For example, in a Web Application/Web API, your Global.asax.cs file is best place to add it once
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;
//Other code...below
}
}
If you don't want to modify the global setting BsonDefaults.GuidRepresentation (and you shouldn't, because modifying globals is a bad pattern), you can specify the setting when you create your collection:
IMongoDatabase db = ???;
string collectionName = ???;
var collectionSettings = new MongoCollectionSettings {
GuidRepresentation = GuidRepresentation.Standard
};
var collection = db.GetCollection<BsonDocument>(collectionName, collectionSettings);
Then any GUIDs written to the collection will be in the standard format.
Note that when you read records from the database, you will get a System.FormatException if the GUID format in the database is different from the format in your collection settings.
It looks like what's happening is when you are not explicitly passing the GuidRepresentation to BsonBinaryData constructor, it defaults to passing GuidRepresentation.Unspecified and that ultimately maps to GuidRepresentation.Legacy (see this line in the source)
So you need to explicitly pass the guidRepresentation as a third argument to BsonBinaryData set to GuidRepresentation.Standard.
edit: As was later pointed out, you can set BsonDefaults.GuidRepresentation = GuidRepresentation.Standard if that's what you always want to use.