How to get Solr field type - java

Is there any way of getting the metadata for a solr core ?
For instance I know the core name, and can obtain a SolServer from that and I also know the field name.
Is there any way to determine the metadata though. Specifically I would like to know whether the field type is an int or a double.
Thanks

You can make a request to the luke request handler:
http://localhost:8983/solr/corename/admin/luke?show=schema&wt=json&_=1453816769771
The output will include the schema for the core, along with the defined fields, their settings and their types:
{"fields":{"xyz":{"type":"string","flags":"I-S-M---OF-----l","copyDests":[],"copySources":[]}, .... }
A neat trick to find these endpoints is to watch the 'network' tab when browsing the admin interface to Solr, as the admin interface is just a static HTML / Javascript frontend that makes all the requests for actual content from the Solr server behind the scenes.

Related

Is there a way to retrieve the ADTs? It doesn't seem like using DDMTemplateLocalServiceUtil is the way to go

I'm trying to get all the adts of a website knowing it's groupid. However, it seems like the adts are mixed up with all the other templates of the site in the DDMTemplate table in the Database.
DDMTemplates are a general portal concept to manage templates for different types of portal assets (not only ADTs). DDMTemplateLocalService is a service to use to also list the ADTs for a certain asset type. You need to first fetch your ClassNameId for the desired asset type to render. For example:
com.liferay.portal.kernel.service.ClassNameLocalService.getClassNameId(AssetEntry.class)
for AssetPublisher entries (or BlogsEntry and so on - for all other types of interest).
Having this id, you can query the ADTs of a site (groupId) using:
com.liferay.dynamic.data.mapping.service.DDMTemplateLocalService.getTemplates(long groupId, long classNameId)
Instead of using the *LocalServiceUtil static functions, you could also inject the service using the #Reference annotation. For example #Reference private DDMTemplateLocalService ddmTemplateService;.

Can a Hibernate Search FieldBridge configure facets for dynamic fields?

Using Hibernate Search 5.11.3 with programmatic API (no annotations), is there a way to facet on dynamic fields added in a class or field bridge? I don't see any 'facet' config available in FieldMetadataBuilder when using MetadataProvidingFieldBridge.
I have tried various combinations of luceneOptions.addSortedDocValuesFieldToDocument() and luceneOptions.addFieldToDocument() in the set() method. This successfully updates the index, but I cannot perform facet queries.
I am trying to do a basic attribute facet/filter where I have a generic table of attributes with id/name and attribute values associated with products. For various reasons I am using the programmatic API and especially for attributes I can't make use of the #Facet annotation. So for a product, I added this class bridge to Product.class:
public class ProductClassTagValuesBridge implements FieldBridge
{
#Override
public void set(String name, Object value, Document document, LuceneOptions luceneOptions)
{
Product product = (Product) value;
for (TagValue v : product.getTagValues())
{
Tag tag = v.getTag();
String tagName = "tag-" + tag.getId();
String tagValue = v.getId().toString();
// not sure if this line is required? Have tried with and without
luceneOptions.addFieldToDocument(tagName, tagValue, document);
luceneOptions.addSortedDocValuesFieldToDocument(tagName, tagValue, document);
}
}
}
Then I build my (test) faceting request to search tag-56 (which I confirmed is in the index using Luke):
FacetParameterContext context = queryBuilder.facet()
.name("tag-56")
.onField("tag-56")
.discrete();
FacetingRequest facetingRequest = context.createFacetingRequest();
Which when used in the search/FacetManager gives me the error:
org.hibernate.search.exception.SearchException: HSEARCH000268: Facet request 'TAG_56' tries to facet on field 'tag-56' which either does not exist or is not configured for faceting (via #Facet). Check your configuration.
I have also tried the custom config solution from the solution in this post: Hibernate Search: configure Facet for custom FieldBridge
For the custom field I added a field bridge to tagValues on my product. The same error occurs.
mapping.entity(Product.class).indexed()
.property("tagValues", ElementType.FIELD).field()
.analyze(Analyze.NO).store(Store.YES)
.bridge(ProductTagValuesFieldBridge.class)
Short answer: Hibernate Search does not allow that... yet.
Long answer:
Hibernate Search 5 allows dynamic fields, but does not allow faceting on fields declared in custom bridges.
That is to say, you can add arbitrary values to your index that don't fit a pre-defined schema, but you cannot use faceting on those fields.
Hibernate search 6 allows faceting (now called "aggregations") on fields declared in custom bridges (just declare them as .aggregable(Aggregable.YES)), but does not allow dynamic fields yet.
EDIT: Starting with 6.0.0.Beta7, dynamic fields are supported thanks to field templates. So the rest of my message is not useful anymore.
See this section of the documentation for more information about field templates. It's totally possible to declare an aggregable, dynamic field in your bridge.
Original message about ways to work without dynamic fields (obsolete):
That is to say, if you know the list of tags upon startup, are able to list them all, and are certain they won't change while your application is up, you could declare the fields upfront and use faceting on them. But if you don't know the list of tags upon startup, none of this is possible (yet).
Until dynamic fields are added to Hibernate Search 6, the only solution is to use Hibernate Search 5 and to re-implement faceting yourself. As you can expect, this will be complex and you will have to get your hands dirty with Lucene. You will have to:
Add fields of type SortedSetDocValuesFacetField to your document in your custom bridge.
Ensure Hibernate Search calls FacetsConfig.build on your documents after they are populated. One way to do that (through a hack) would be to declare a dummy #Facet field on your entity, even if you don't use it.
Completely ignore Hibernate Search's query feature and perform faceting yourself from an IndexReader. You can get an IndexReader from Hibernate Search as explained here. There's an example of how to perform faceting in org.hibernate.search.query.engine.impl.QueryHits#updateStringFacets.

Rest Non CRUD search

I've a problem with a GET operation in a REST WS. We have a Front-end panel with several filters for searching customers. The panel contains these filters:
Customer ID (Customer property)
Customer Name (Customer property)
Account number (Account property)
License plate (Vehicle property)
...
In the domain model we have 3 entities:
Customer
Account (A customer could have 1 or more accounts)
Vehicle (An account could have 1 or more vehicles)
How can I implement REST GET operation for this seach?
GET ..../customers/?name={name}&accountNum={accountNumber}&licensePlate={licensePlate} ?????
I think it is wrong because accountNumber and licensePlate don´t belong to customer resource. I don´t need these properties in the result expected.
I think about create new resource like customerFilter but It is no sense if I have to return a customer resource.
Any idea?
Thank you!
It will not pretend to be a specific answer for your question. But I think it will clarify something related to GET method.
According with URI Specification - RFC 3986 and Http Specification - RFC 7230, there are 3 kinds of ways to send data from client to server: via query, via path or via message-body.
When you are using GET method, it is not recommended to use message-body, because GET method can be cached for improving performance stuffs and these caches could ignore the message-body or reject the request:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
So, you can choose now query or path. Both are in URL in this format:
http://example.com/{path1}/{path2}?query1=value1&query2=value2
What are the differences between these? according with RFC 3986 - Path and RFC 3986 - Query:
The path component contains data, usually organized in hierarchical
form, that, along with data in the non-hierarchical query component
(Section 3.4), serves to identify a resource within the scope of the
URI's scheme and naming authority (if any).
The query component contains non-hierarchical data that, along with
data in the path component (Section 3.3), serves to identify a
resource within the scope of the URI's scheme and naming authority
(if any).
As conclusion, you can design whatever you want. You can use for example:
GET .../customers?name={name}&accountNum={accountNumber}&licensePlate={licensePlate}
GET .../customers/{customerId}/
GET .../customers?customerId=12345
I don't see any issue with the url you have but your concern is also valid.
There is something that we need to take into consideration in this scenario. With this search what you expect to get as the response of the API call?
If you want response should contain information about customer only, when the search condition gets satisfied then /customer is right.
If you want some generic response consisting of Customer, Account and Vehicle info, you can have some generic terminology instead of customer in the url.
I hope this will help you.
Thanks :)

How to switch a Spring Roo or Grails project from typical MVC to AJAX/JSON/REST

This might seem like an odd question, but I am trying to get a handle on what the "best practice" is for converting an application that is set up to use something like Roo's or Grails' generation of controllers (which provides basic CRUD functionality) to something that returns a JSON response body instead for use in a JavaScript application.
The ambiguity of technology here is because I haven't actually started the project yet. I am still trying to decide which (Java-based) technology to use, and to see what kind of productivity tools I should learn/use in the process. It will be a web application, and it will use a database persistence layer. All other details are up in the air.
Perhaps the easiest way to accomplish my goal is to develop using some sort of AJAX plugin to start with, but most of the tutorials and descriptions out there say to start with a normal MVC architecture. Roo seems to make conversion of the controllers it generates to JSON-friendly return types difficult, and I'm not familiar enough with Groovy/Grails to know what it takes to do that.
This is mostly a learning experience for me, and I am open to any criticism or advice, but being a Q/A forum, I realize I need to incorporate an objective question of some sort. To fill that need, I ask:
What is the best way to set up an AJAX/RESTful interface for my entities in Roo and/or Grails?
I recently did exactly this with a Grails application and found it surprisingly easy to take the generated controllers and get them to output JSON or XML or the HTML from the view depending on the content negotiation.
The places in the Grails manual to look into are the section(s) on Content Negotiation and, if you need to deal with JSON or XML input, marshaling.
To get JSON and XML output, in the default list() method, changed it to this (I have a Session object, in this case...one of my domain classes):
def list() {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
def response = [sessionInstanceList: Session.list(params), sessionInstanceTotal: Session.count()]
withFormat {
html response
json {render response as JSON}
xml {render response as XML}
}
}
Anywhere you are returning just an object by default, you will want to replace the returned value with the withFormat block.
You also may need to update your Config.groovy file where it deals with mime types. Here's what I have:
grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
grails.mime.use.accept.header = true
grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
xml: ['text/xml', 'application/xml'],
text: 'text/plain',
js: 'text/javascript',
rss: 'application/rss+xml',
atom: 'application/atom+xml',
css: 'text/css',
csv: 'text/csv',
all: '*/*',
json: ['application/json','text/json'],
form: 'application/x-www-form-urlencoded',
multipartForm: 'multipart/form-data'
]
As input (to an update() or save() action, for example) JSON and XML payloads will automatically be unmarshaled and will be bound just like a form input would be, but I've found that the unmarshaling process is a bit picky (especially with JSON).
I found that, in order for JSON to be handled correctly in the update() method, the class attribute had to be present and correct on the inbound JSON object. Since the library I was using in my client application didn't make this an easy issue to deal with, I switched to using XML instead.

Spring "typemismatch" and required fields

In the context of Spring Webflow 2.0.x......
I handle form binding "typemismatches", i.e. as a result of trying to map a String onto a Integer field, by using the following in my messages.properties
typeMismatch={0} contains invalid data.
This works fine.
The problem is that if the field that the typeMismatch error occurred on was "required" then I also receive an error for the missing required field, which is logical I guess because the value that was submitted was never bound. ("Required" being defined in a Commons Validation XML file)
So, I dont want to see the "XXX is required field" error message when the field is only missing due to the typeMismatch. How do I resolve this? I thought about overriding initBinder() on the FormAction but quickly got nowhere.....
Like Yves mentioned, among the three approaches, i have used a custom validator method and its very easy. You can use a custom validator which checks if the form field already has a xml error message of required. If the field does not have an error, then you can check for your string validation. That way it will display only one.
The other method that you could use is try a multiple xml validation, one being required and the other one being a mask which checks for a particular regular expression. In your case if your field is an integer field, then you can go and perform a mask with regex checking for only numbers. The order of mask, required or required, mask in the xml decides which message gets a higher preference.
For example:
<field property="somefield" depends="required,mask" page="2">
<arg key="somelabel"/>
<var>
<var-name>mask</var-name>
<var-value>${somepattern}</var-value>
</var>
</field>
You have many options, in order of preference:
Set selectively the message typeMismatch.target.yourFieldName or typeMismatch.int in resources files
Implement your own Validator so that you can send a dedicated message when Integer parsing will fail before the binding step
Create a BindingErrorProcessor to handle different kind of parsing issues

Categories

Resources