Javers QueryBuilder Pagination Support - javers

UseCase :: How to write query using javers query builder that can support pagination while fetching audit's logs for api's.

One possible way to write query is by using skip() and limit().
#Service
public class AuditService {
#Autowired
Javers javer;
public List<Change> fetchAudits(String auditer,Integer offset,Integer limit) {
return javer.findChanges(QueryBuilder.anyDomainObject().byAuthor(auditer).skip(offset).limit(limit).build());
}
}

Related

Returning only the first 10 record - Redis OM

I’m using Redis OM for spring boot, I am having trouble querying objects because it only returns the first 10 records.
Repository Class:
public interface RedisBillerRepository extends RedisDocumentRepository<Biller, Long> {
List<Biller> findByClientIds(String clientId);
}
Is there a way to return ALL the objects with the specific clientId? Not the first 10 only.
The only way which i found was with the interface Page. For example your Repository would look like this:
public interface RedisBillerRepository extends RedisDocumentRepository<Biller, Long> {
Page<Biller> findByClientIds(String clientId, Pageable pageable);
}
And your class could look like this
public class BillerService {
#Autowired
RedisBillerRepository redisBillerRepository;
public List<Biller> getAllClientsById(String clientId){
Pageable pageRequest = PageRequest.of(0, 500000);
Page<Biller> foundBillers = redisBillerRepository.findByClientIds(clientId, pageRequest);
List<Biller> billersAsList = foundBillers.getContent();
return billersAsList;
}
}
You have to set the limit for now.
I'm the author of the library... #member2 is correct. RediSearch currently has a default for the underlying FT.SEARCH (https://redis.io/commands/ft.search/) method of returning the first 10 records found. To override that, the only way to do so currently is to use the Pagination constructs in Spring.
I will expose a configuration parameter in upcoming versions to set the MAX globally.

Spring Data - Build where clause at runtime

In Spring Data, how can I append more conditions to an existing query?
For example, I have the CrudRepository below:
#RepositoryRestResource
public interface MyRep extends CrudRepository<MyObject, Long> {
#Query("from MyObject mo where mo.attrib1 = :attrib1")
List<MyObj> findMyObjects(String attrib1, String conditions);
}
At runtime, I will need to call "findMyObjects" with two params. The first param is obviously the value of attrib1. the second param will be a where clause that would be determined at runtime, for example "attrib2 like '%xx%' and attrib3 between 'that' and 'this' and ...". I know this extra where condition will be valid, but I don't know what attributes and conditions will be in it. Is there anyway to append this where clause to the query defined in the #Query annotation?
Unfortunately, no. There is no straightforward way to achieve that.
You'll want to use custom reporistory methods where you'll be able to inject an EntityManager and interact with EntityManager.createQuery(...) directly.
Alternatively, you can build dynamic queries using Specifications or QueryDsl.
I ended up injecting an EntityManager that I obtained in the rest controller. Posting what I did here for criticism:
The repository code:
#RepositoryRestResource
public interface MyRepo extends CrudRepository<MyObject, Long> {
default List<MyObject> findByRuntimeConditions(EntityManager em, String runtimeConditions) {
String mySql = "<built my sql here. Watch for sql injection.>";
List<MyObject> list = em.createQuery(mySql).getResultList();
return list
}
}
The Rest controller code:
#RestController
public class DataController {
#Autowired
EntityManager em;
// of course watch for sql injection
#RequestMapping("myobjects/{runtimeConditions}")
public List<MyObject> getMyObjects(#PathVariable String runtimeConditions) {
List<MyObject> list = MyRepo.findByRuntimeConditions(em, runtimeConditions);
return list;
}
}

In Spring data solr 3.0.6 release , choose solr core dynamically

I am using spring data solr 3.0.6, and standalone solr server 7.0.0 and I have multiple solr cores in my solr server, and I want to choose one of them dynamically , Here is the configuration I Have
#Configuration
#EnableSolrRepositories(basePackages = "com.solr.repository")
public class SolrConfiguration
{
#Bean
public SolrOperations solrTemplate(SolrClient solr) {
return new SolrTemplate(solr);
}
#Bean(name = "solrClient")
public SolrClient createSolrClient()
{
HttpSolrClient.Builder builder = new HttpSolrClient.Builder().withBaseSolrUrl(solrInstanceUrl);
return builder.build();
}
}
SolrRepository
public interface SolrRepository extends SolrCrudRepository<SolrDocument, Integer>
{
#Query("name:*?0* OR content:*?0*")
#Highlight()
public HighlightPage<SolrDocument> findByQueryAnnotation(String searchTerm, Pageable pageable);
}
SolrDocument (domain class for Solr repository)
#SolrDocument
public class SolrDocument
{
}
ServicePojo (service class)
public class ServicePojo
{
#Autowired
SolrRepository solrRepository;
public void findData(int id)
{
solrRepository.findById(id);
}
}
Now I want to use methods of repository interface like findById() etc, but as I mentioned above, I have different cores, and I want to point a specific core to perform searching, before calling method solrRepository.findById() I need to mention which core it should point. So where we can tell to solr server , which Core to be used ?
If I use annotation #SolrDocument(collectionName="core1"), then it works fine and it points to "core1", but I want this to be dynamic. Please help
You cannot do this using Repository (SolrRepository). But you can do this using SolrTemplate.
Here is the link to the 3.0.6 SolrTemplate API. If you look at some of the methods like query or getById, it takes an argument collectionName. You can pass coreName here.

Spring filter collection first and then apply pagination

I have following code in my Spring RestController
Page<Message> messages = messagesRepository.findAll(new PageRequest(page, size, new Sort(Sort.Direction.DESC, "id")));
return messages.getContent().stream().filter(Message::isPublished).collect(Collectors.toList());
I would like to apply the filter on my collection first (only get the published messages) and then apply a PageRequest on it. How can I do that? Currently it is the other way around which does not return the expected result.
Just create a query method that will return only published messages. Something like this:
public interface MessageRepository extends JpaRepository<Message, Long> {
Page<Message> findByPublishedIsTrue(Pageable pageable);
}
Supported query keywords.

Defining query consistency in Spring Data Couchbase

I try to establish a deleteAll function which deletes all documents which are associated with a given repository and class. In order to this I created a custom N1ql query. But I want the Couchbase index to be updated before later database operations take place. My guess is that I have to change the consistency level of the query to achieve this behaviour.
Here and here I found some examples which do this by using the CouchbaseTemplate. But my template is null. Could anybody tell me what I am doing wrong?
public void deleteAll() throws DBException {
CouchbaseOperations couchbaseTemplate;
try {
couchbaseTemplate = templateProvider.resolve(getRepository().getClass(), getClassName().getClass());
} catch (Exception e) {
throw new DBException("Could not get couchbase client", e);
}
String statement = String.format("DELETE FROM %s WHERE _class='%s'",
couchbaseTemplate.getCouchbaseBucket().name(), getClassName());
ScanConsistency consistency = couchbaseTemplate.getDefaultConsistency().n1qlConsistency();
N1qlParams queryParams = N1qlParams.build().consistency(consistency);
N1qlQuery query = N1qlQuery.simple(statement, queryParams);
N1qlQueryResult result = couchbaseTemplate.queryN1QL(query);
//Result handling
}
}
The templateProvider is autowired.
It is not entirely clear about your repository and entity from your code snippet. Which version of SDC are you using?
If you are using operation mapping bean, you get the underlying couchbase template for the particular repository and entity using
#Repository
public interface MyRepository extends CrudRepository<MyEntity, String> {
}
public class MyService {
#Autowired
MyRepository repo;
#Autowired
RepositoryOperationsMapping templateProvider;
....
CouchbaseOperations operations = templateProvider.resolve(repo.getClass(),MyEntity.class);
Make sure to enable couchbase repositories with #EnableCouchbaseRepositories. If your repositories only use couchbase, you can also get the couchbase template bean directly.
#Autowired
CouchbaseTemplate template;

Resources