How to select shard for search query? - hibernate-search

I'm recently implemented ShardIdentifierProvider. It is working fine. But how to ensure it is using only one shared for query?
public class SiteIdAsShardIdProvider extends ShardIdentifierProviderTemplate {
#Override
protected Set<String> loadInitialShardNames(Properties properties, BuildContext buildContext) {
ServiceManager serviceManager = buildContext.getServiceManager();
SessionFactory sessionFactory = serviceManager.requestService(HibernateSessionFactoryServiceProvider.class, buildContext);
Session session = sessionFactory.openSession();
try {
#SuppressWarnings("unchecked")
List<String> ids = session.createSQLQuery("select cast(id as CHAR(3)) from website").list();
return new HashSet<>(ids);
} finally {
session.close();
}
}
#Override
public String getShardIdentifier(Class<?> entityType, Serializable id, String idAsString, Document document) {
return document.getFieldable("siteId").stringValue();
}
}

Creating your own custom filter and overriding getShardIdentifiersForQuery should do the trick. Here is something that does approximately the same as what's in the documentation, but with a ShardIdentifierProviderTemplate:
#Override
public Set<String> getShardIdentifiersForQuery(FullTextFilterImplementor[] filters) {
FullTextFilter filter = getFilterByName( filters, "customer" );
if ( filter == null ) {
return getAllShardIdentifiers();
}
else {
Set<String> result = new HashSet<>();
result.add( filter.getParameter( "customerID" ) );
return result;
}
}
private FullTextFilter getFilterByName(FullTextFilterImplementor[] filters, String name) {
for ( FullTextFilterImplementor filter: filters ) {
if ( filter.getName().equals( name ) ) {
return filter;
}
}
return null;
}
I created a ticket to update the documentation: https://hibernate.atlassian.net/browse/HSEARCH-2513

The shard selection at query time is controlled by using a custom Filter.
See "5.3.1. Using filters in a sharded environment" for details and examples.

Related

Sorting in NatTables

I have got implemented filtering in nattables. How to add sorting? do I have to create new columnHeaderLayer? Here is my code:
1 class BodyLayerStack
class BodyLayerStack extends AbstractLayerTransform {
private final FilterList<TableLine> filterList;
private final SelectionLayer selectionLayer;
private final DataLayer bodyDataLayer;
private final IRowDataProvider<TableLine> bodyDataProvider;
private final SortedList<TableLine> sortedList;
public DataLayer getBodyDataLayer() {
return bodyDataLayer;
}
public SelectionLayer getSelectionLayer() {
return selectionLayer;
}
public IRowDataProvider<TableLine> getBodyDataProvider() {
return bodyDataProvider;
}
getting values from tables:
public BodyLayerStack(List<TableLine> values, IColumnAccessor<TableLine> columnAccessor, Integer[] columnIndicesForRowHeaders) {
EventList<TableLine> eventList = GlazedLists.eventList(values);
TransformedList<TableLine, TableLine> rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);
creating filter and sorted list:
this.filterList = new FilterList<>(rowObjectsGlazedList);
this.sortedList = new SortedList<>(filterList, null);
this.bodyDataProvider = new ListDataProvider<TableLine>(this.sortedList, columnAccessor);
bodyDataLayer = new DataLayer(this.bodyDataProvider);
ColumnOverrideLabelAccumulator bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);
if( columnIndicesForRowHeaders != null ) {
for ( int i = 0; i < columnIndicesForRowHeaders.length; i++ ) {
bodyLabelAccumulator.registerColumnOverrides(
columnIndicesForRowHeaders[i],
RowHeaderLabel);
}
}
event layer:
GlazedListsEventLayer<TableLine> glazedListsEventLayer =
new GlazedListsEventLayer<>(bodyDataLayer, this.filterList);
this.selectionLayer = new SelectionLayer(glazedListsEventLayer, false);
selectionLayer.setSelectionModel(new RowSelectionModel<TableLine>(selectionLayer, this.bodyDataProvider, new IRowIdAccessor<TableLine>()
{
#Override
public Serializable getRowId(TableLine line)
{
return line.getId();
}
}));
adding configuration to selection layer
selectionLayer.addConfiguration(new DefaultSelectionLayerConfiguration()
{
#Override
protected void addSelectionUIBindings()
{
addConfiguration(new SelectionBindings());
}
#SuppressWarnings("rawtypes")
#Override
protected void addMoveSelectionConfig()
{
addConfiguration(new RowOnlySelectionConfiguration());
}
});
viewport layer + return
ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
setUnderlyingLayer(viewportLayer);
}
public FilterList<TableLine> getFilterList() {
return this.filterList;
}
}
If you want to add sorting by click on column header cells, you have to add the SortHeaderLayer to your column header layer stack.
Please check the NatTable examples, like for example the SortableFilterableColumnGroupExample

Query with parameters - AWS Amplify - Android

I am having trouble figuring out how to pass a parameter to a query. In this case, I want to get a user by name field. I know I can pass an id, but how do I pass another field? Do I need to create a secondary index?
private AWSAppSyncClient mAWSAppSyncClient;
mAWSAppSyncClient.query(GetUserQuery.builder().build())
.responseFetcher(AppSyncResponseFetchers.CACHE_AND_NETWORK)
.enqueue(userCallback);
query GetUser($id: ID!) {
getUser(id: $id) {
id
userId
name
...
}
}
Use ListUsers (ListXXXX) to query with multiple parameters.
Example - query by name = "aaa":
ModelStringFilterInput modelStringFilterInput = ModelStringFilterInput.builder().eq("aaa").build();
ModelUserFilterInput modelUserFilterInput = ModelUserFilterInput.builder().name(modelStringFilterInput).build();
mAWSAppSyncClient.query(ListUsersQuery.builder().filter(modelUserFilterInput).build())
.responseFetcher(AppSyncResponseFetchers.CACHE_AND_NETWORK)
.enqueue(userCallback);
private GraphQLCall.Callback<ListUsersQuery.Data> userCallback = new GraphQLCall.Callback<ListUsersQuery.Data>() {
#Override
public void onResponse(#Nonnull Response<ListUsersQuery.Data> response) {
Log.d(TAG, response.data().listUsers().items().toString());
}
#Override
public void onFailure(#Nonnull ApolloException e) {
Log.d(TAG, e.toString());
}
};

REST service for PUMA search users by createTimestamp

Is it possible to find users by createTimestamp attribute on REST service for PUMA? Search for other attributes works well, but if the type attribute is the dateTime I get different errors, such as http://www-01.ibm.com/support/docview.wss?uid=swg1PM54864.
I need to find users who were created earlier some date.
I tried this:
host/wps/um/secure/users/profiles?searchAttributes=createTimestamp>=yyyyMMddHHmmssZ
host/wps/um/secure/users/profiles?searchAttributes=createTimestamp>=yyyy-MM-dd'T'HH:mm:ss
host/wps/um/secure/users/profiles?searchAttributes=createTimestamp>=yyyy-MM-dd'T'HH:mm:ss'Z'
and even equality is not working
host/wps/um/secure/users/profiles?searchAttributes=createTimestamp=yyyy-MM-dd'T'HH:mm:ss'Z'
I solved this problem through ldap.
#Service
public class LdapService {
#Autowired
private LdapTemplate ldapTemplate;
private SearchControls searchControls;
#PostConstruct
private void init() {
searchControls = new SearchControls();
searchControls.setCountLimit(10000);
searchControls.setSearchScope(SUBTREE_SCOPE);
}
private class MemberMapper implements ContextMapper {
public Member mapFromContext(Object ctx) {
Member member = new Member();
DirContextAdapter adapter = (DirContextAdapter) ctx;
Attribute valueMail = adapter.getAttributes().get("mail");
try {
member.setEmail(valueMail == null ? null : valueMail.get().toString().trim());
} catch (Exception ignore) {
}
Attribute valueCN = adapter.getAttributes().get("cn");
try {
member.setLogin(valueCN == null ? null : valueCN.get().toString().trim());
} catch (Exception ignore) {
}
return member;
}
}
public List<Member> getUsersByCreateTimestamp() {
AndFilter andFilter = new AndFilter();
andFilter.and(new GreaterThanOrEqualsFilter("createTimestamp" "20160803000000"));
andFilter.and(new LessThanOrEqualsFilter("createTimestamp", "20160804000000"));
List<Member> allMembers = new ArrayList<Member>();
List<Member> members = ldapTemplate.search("", andFilter.encode(), searchControls, new MemberMapper());
allMembers.addAll(members);
return allMembers;
}

How to retrieve an embedded list of object of Entity?

I have a simple problem storing and retrieving an embedded collection of entity to mongo. I have checked theses question :
how to serialize class? and Mongodb saves list of object
what I understand is to save a list objects the class of that objects must extends ReflactionDBObject. This worked for saving the object, by retrieving it with the embedded collection does not work.
here a simple test show that retrieving embedded entities does not work !
#Test
public void whatWasStoredAsEmbeddedCollectionIsRetrieved2() {
BasicDBObject country = new BasicDBObject();
country.put("name", "Bulgaria");
List<City> cities = Lists.newArrayList(new City("Tarnovo"));
country.put("listOfCities", cities);
DBCollection collection = db().get().getCollection("test_Collection");
collection.save(country);
DBCursor object = collection.find(new BasicDBObject().append("name", "Bulgaria"));
DBObject returnedCity = object.next();
DBObject embeddedCities = (DBObject) returnedCity.get("listOfCities");
System.out.println(embeddedCities);
}
Here is the City Class
class City extends ReflectionDBObject {
String name;
City() {
}
City(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof City)) return false;
City city = (City) o;
if (name != null ? !name.equals(city.name) : city.name != null) return false;
return true;
}
#Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
#Override
public String toString() {
return "City{" +
"name='" + name + '\'' +
'}';
}
}
The out put of the System.out.println statement is [ { "_id" : null }]
Now how can get back the embedded object and the embedded list in it ?
If you do not have a requirement to define your own class City, you can define subdocuments using the BasicDBObjects. I only added the 'name' field to the citySubDoc1 and citySubDoc2, but of course, you can add more fields to these subdocuments.
// Define subdocuments
BasicDBObject citySubDoc1 = new BasicDBObject();
citySubDoc1.put("name", "Tarnovo");
BasicDBObject citySubDoc2 = new BasicDBObject();
citySubDoc2.put("name", "Sofia");
// add to list
List<DBObject> cities = new ArrayList <DBObject>();
cities.add(citySubDoc1);
cities.add(citySubDoc2);
country.put("listOfCities", cities);
collection.save(country);
// Specify query condition
BasicDBObject criteriaQuery = new BasicDBObject();
criteriaQuery.put("name", "Bulgaria");
// Perform the read
DBCursor cursor = collection.find(criteriaQuery);
// Loop through the results
try {
while (cursor.hasNext()) {
List myReturnedListOfCities = (List) cursor.next().get("listOfCities");
System.out.println(myReturnedListOfCities);
}
} finally {
cursor.close();
}

Implemention Class proposal mechanism in SWT field

i know how to implement it,using field assist and search pattern, but the mechanism each time triggers a new search. I am not sure, how the mechanism is implemented in Open Type for example ( i think with indexes). How to use this cache to make in time classpath search
This almost my entire solution. Each time a call createProposalData
private TreeSet<String> data;
private SearchParticipant[] participants = new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() };
private SearchPattern pattern;
private IJavaProject prj;
private JavaSearchScope scope;
private SearchEngine searchEngine = new SearchEngine();
private SearchRequestor requestor = new SearchRequestor() {
#Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
String text = getText(match.getElement());
if (text != null) {
data.add(text);
}
}
public String getText(Object element) {
...
}
};
public ProposalEngine(IJavaProject prj) {
super();
this.prj = prj;
scope = new JavaSearchScope();
try {
scope.add(prj);
} catch (JavaModelException e) {
//
}
}
public Collection<String> createProposalData(final String patternText) {
data = new TreeSet<String>();
try {
pattern = getPatternForSeach(patternText);
searchEngine.search(pattern, participants, scope, requestor, null);
} catch (Exception e) {
// skip
}
return data;
}
protected SearchPattern getPatternForSeach(String patternText) {
return SearchPattern.createPattern(patternText,
IJavaSearchConstants.CLASS_AND_INTERFACE,
IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_CAMELCASE_MATCH);
}
I believe that you are doing exactly what the Open Type dialog is doing. Indexing to speed up search happens underneath JDT API.