Elasticsearch repository not allowing default field type - spring-data-elasticsearch

While creating an index Elasticsearch Repository does not allow default type. If field type annotation is missing, assuming default type, the Spring data elasticsearch mapper throws exception and then creates some default mapping when I save the first object.
I'm wondering if it is somehow possible to not annotate every field in of my data objects?
I'm using Spring Data Elasticsearch v3.1.8 and Elasticsearch 6.2.2.
Thanks

There is effectively a way to avoid annoting every fields. Elasticsearch need to create the mapping of the document.
You can indicate to spring how the document need to be mapped with #Field or by providing the mapping configuration.
With spring just annotate the document with #Mapping to set mapping file location.
Also you could just create the mapping using Elasticsearch PUT mapping API.
#Document(indexName = Produit.INDEX, type = ProduitES.TYPE, shards = 1)
#Mapping(mappingPath = "/mappings/mappings-produit.json")
public class Produit {
private String code;
private String name;
...
}
The mapping file in resources/mappings/mappings-produit.json folder :
{
"produit": {
"dynamic": "strict",
"properties": {
"code": {
"type": "text",
},
"name": {
"type": "text",
"index": false
}
}
}
}

Related

Swagger + Nest.js doesn't remove empty DTO and model

I was creating documentation for Nest.js API using Swagger. The problem is what I removed documentation from this DTO or model, in swagger UI docs I can see it as empty object.
For example:
import { IsNotEmpty } from 'class-validator';
export class PostDto {
#IsNotEmpty()
readonly title: string;
#IsNotEmpty()
readonly content: string;
#IsNotEmpty()
readonly description: string;
}
Also I was trying to change name of this entity, using incognito mode, reinstall node_modules, but it didn't work. If I change name of this entity, it also changes there. What's wrong?
What I want to do, is by removing this documentation decorators, not to see those empty objects.
There is a CLI plugin provided with the #nestjs/swagger which will automatically add the annotations using reflection.
This means you NO LONGER need to individually annotate each property using #ApiProperty() etc.
The plugin is opt-in and not active by default.
In your nest-cli.json add:
{
"collection": "#nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["#nestjs/swagger"]
}
}
You can also change the default options:
"plugins": [
{
"name": "#nestjs/swagger",
"options": {
"classValidatorShim": false,
"introspectComments": true
}
}
]
See https://docs.nestjs.com/openapi/cli-plugin
Troubleshooting: if you are running in dev mode, may need to stop/start.

How to generate whole Pageable Object with Swagger Codegen instead of each properties inside it?

I have an API to retrive all products with Paging and Sorting functions as follow:
#ApiImplicitParams({
#ApiImplicitParam(name = "page", dataType = "integer", paramType = "query", value = "The page number that should be returned. Default is 0."),
#ApiImplicitParam(name = "size", dataType = "integer", paramType = "query", value = "How many items the page should have. Default is 20."),
#ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "Sorting order, e.g. asc or desc. Default is asc")})
public ResponseEntity<Product[]> getAllProducts(Pageable pageable) {}
And then I use Codegen to generate Client API but the problem here is the method's signature that it generated is not the one that I am expecting:
public List<Product> getAllProductsUsingGET(Object page, Object size, List<String> sort){}
What I would like to have here is getAllProductsUsingGET(Pageable pageable)
Did I make some mistake with the configuration? Can anyone give me some hint how to achieve only pageable as parameter instead of each single property like that? Thank you very much!
you are defining the API implicit parameters to include exactly those 3 parameters. Nonetheless, I don't think the final API should contain signatures that include Pageable params as these are dependency of Spring and you don't want your "connector" API to bring Spring dependencies attached.

How do you properly bind a list of objects into a Grails command?

I'm trying to figure out how to deserialize and validate nested objects in JSON request into a Grails 2.1.1 command object.
Currently I have a command object in my controller that has a few basic properties and then list of domain objects,
protected static class CustomCommand {
String name
String description
List<DomainObject> objs
}
And a JSON body to my POST request,
{
name: 'test name',
description: 'test description',
objs: [
{
name: 'test sub object',
description: 'test description'
}
]
}
I'm seeing the command object created with an empty array. Any idea how I can get the sub objects my in JSON body to deserialize into the command object and then validate them?
Previously I've worked around this by manually creating an object from the parameter map and validating that directly, but that feels like a workaround that isn't taking advantage of everything Grails offers.
We had a similiar issue with binding post data to a list inside a command. Our workaround that worked was to define a default value for collection elements:
class MyCommand {
List<MyClass> items= [].withLazyDefault {
new MyClass()
}
}
After that the post data was correctly bound to the list. I think the reason is that Groovy ignores the generic type parameter of the list and does not know which object to instantiate at runtime.
I'am not sure if this works in your case but it might be worth a try
Update:
I used this a few minutes ago:
public static class MyCommand {
String foo
List<Bar> bars
public String toString() {
return "foo: " + foo + ", bars: " + bars
}
}
public static class Bar {
String baz
}
controller method:
def test() {
println new MyCommand(request.JSON)
}
I posted some json using jquery:
$.ajax({
type: "POST",
url: '...',
data: JSON.stringify({
'foo': '12345',
bars: [
{baz: '1'},
{baz: '2'}
]
}),
contentType : 'application/json',
});
The output printed by the controller:
foo: 12345, bars: [[baz:1], [baz:2]]
So it seems to work :o
I never got this to work under Grails 2.1.1, but apparently this was fixed in Grails 2.3,
Binding Request Body To Command Objects
If a request is made to a controller action which accepts a command object and the request includes a body, the body will be parsed and used to do data binding to the command object. This simplifies use cases where a request includes a JSON or XML body (for example) that can be bound to a command object. See the Command Objects documentation for more details.

Specify Candidate Key In grails?

How can i specify "name" as primary key...by specifying through domain class groovy file.. i'm working in fedora as OS and through terminal (not using ggts or any tools) and using database as MySQL
class Department {
String name
String description
}
To change which field is your primary key, you can use the id mapping entry like so:
class Department {
String name
static mapping = {
id name: 'name', generator: 'assigned'
}
}
You can read more details about the options on the id entry in the Grails Documentation.

Unable to create new domain object in Grails

Hi there i am still very new to grails and I have not been able to figure out why this is happening.
I have a domain class:
package scheduler
class Client {
String name
static constraints = {}
}
And a controller:
package scheduler
class AdminController {
def create() {
def client = new Client(name:"John")
println client
}
}
Currently I am always getting null for client. Originally the above was a little more complex on the domain class side but I systematically dumbed it down to see if it was a problem there. I still can not get the above working.
The output is always
scheduler.Client : null
Please let me know if I need to provide anymore information.
It's not null, that's just the default output of the toString method that Grails adds. It prints the class name and the id. Since you haven't saved the instance, the id is null. If the instance was null the output would have been null, not scheduler.Client : null
If you want to see the data in the instance, use the Groovy dump() method, e.g.
def client = new Client(name:"John")
println client.dump()
You could also add a toString method that includes the name attribute, e.g.
package scheduler
class Client {
String name
String toString() { name }
}

Resources