Creating Nested Query in Spring Data Elasticsearch - spring-data-elasticsearch

I am totally new to Spring Data Elasticsearch and trying to build a query like the one below;
Any help would be greatly appreciated.
{
"query":{
"bool":{
"must":[
{
"bool":{
"should":[
{
"match_phrase":{
"firstPhrase":"A"
}
},
{
"match_phrase":{
"secondPhrase":"B"
}
},
{
"nested":{
"path":"things",
"query":{
"bool":{
"should":[
{
"match_phrase":{
"another.phraseOne":"C"
}
},
{
"match_phrase":{
"another.phraseTwo":"D"
}
}
]
}
}
}
}
]
}
},
{
"match_phrase":{
"otherPhase":"E"
}
}
]
}
}
}
I started with creating the first two boolean queries;
BoolQueryBuilder firstBool = QueryBuilders.boolQuery()
.should(QueryBuilders.matchPhraseQuery("firstPhrase", "A"))
.should(QueryBuilders.matchPhraseQuery("secondPhrase", "B"));
BoolQueryBuilder secondBool = QueryBuilders.boolQuery()
.should(QueryBuilders.matchPhraseQuery("another.phraseOne", "C"))
.should(QueryBuilders.matchPhraseQuery("another.phraseTwo", "D"));
Then I tried to create a nested query (Not sure how to use ScoreMode);
QueryBuilder nestedQuery= nestedQuery("things",secondBool, ScoreMode.None);
I created another match-phrase which is in the must;
QueryBuilder third = QueryBuilders.matchPhraseQuery("otherPhrase", "E");
I am not sure how to add them all to create the structure I have and most importantly not sure how to add the nested query to the "must".
QueryBuilder allQueries = new BoolQueryBuilder()
.must(first)
.must(second)
.must(third);
And finally, using them all at once;
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(allQueries).build();
Would this be a right approach to achive what I am trying to generate?

You almost had it, rearranging the order of querybuilding:
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
class Scratch {
public static void main(String[] args) {
BoolQueryBuilder boolShouldCD = QueryBuilders.boolQuery()
.should(QueryBuilders.matchPhraseQuery("another.phraseOne", "C"))
.should(QueryBuilders.matchPhraseQuery("another.phraseTwo", "D"));
QueryBuilder nestedQuery= QueryBuilders.nestedQuery("things",boolShouldCD, ScoreMode.None);
BoolQueryBuilder boolShouldABNested = QueryBuilders.boolQuery()
.should(QueryBuilders.matchPhraseQuery("firstPhrase", "A"))
.should(QueryBuilders.matchPhraseQuery("secondPhrase", "B"))
.should(nestedQuery);
QueryBuilder allQueries = new BoolQueryBuilder()
.must(boolShouldABNested)
.must(QueryBuilders.matchPhraseQuery("otherPhrase", "E"));
System.out.println(allQueries.toString());
}
}
This is plain Elasticsearch client code, to use that in Spring Data Elasticsearch using the NativeSearchQueryBuilder is the right way to go.
After inlining and static imports you get this shorter code:
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import static org.elasticsearch.index.query.QueryBuilders.*;
class Scratch {
public static void main(String[] args) {
QueryBuilder allQueries = new BoolQueryBuilder()
.must(boolQuery()
.should(matchPhraseQuery("firstPhrase", "A"))
.should(matchPhraseQuery("secondPhrase", "B"))
.should(nestedQuery("things", boolQuery()
.should(matchPhraseQuery("another.phraseOne", "C"))
.should(matchPhraseQuery("another.phraseTwo", "D")), ScoreMode.None)))
.must(matchPhraseQuery("otherPhrase", "E"));
System.out.println(allQueries.toString());
}
}

Related

connecting vertices in jung by edges results in another extra vertex being created

I am implementing an interface for taking commands for creating , connecting and coloring vertices in JUNG when I want to connect two already existing vertices JUNG connects to vertices and creates an extra vertex , why?
Here is my code for connect method:
public class Connect extends Command {
private CommandMaster cm;
private BehGraphUndirected behGraph;
private static int edgenumber=0;
#Override
public Object run(BehGraphUndirected behGraph, VisualizationImageServer panel, InterpretMaster interpretMaster, String... args) {
System.out.print("connect Runs\n");
this.cm = new CommandMaster();
this.behGraph = behGraph;
if(cm.exists(args[0]))
{
//got to another command
}else
{
switch (args[0]) {
case "edge":
this.createEdge(args[1] , args[2]);
break;
}
}
interpretMaster.refreshAndRepaint();
return null;
}
public void createEdge(String nodeName1 , String nodeName2)
{
this.behGraph.addEdge(edgenumber++,nodeName1, nodeName2);
System.out.println(this.behGraph.getVertexCount());
System.out.println("edge between: "+nodeName1+" and "+ nodeName2+" added");
}
And it's the create method just in case you want to know the way I implemented the code:
package interpreter.command;
import GraphHandling.BehGraphUndirected;
import edu.uci.ics.jung.visualization.VisualizationImageServer;
import interpreter.Command;
import interpreter.CommandMaster;
import interpreter.InterpretMaster;
/**
*
* #author Administrator
*/
public class Create extends Command{
private CommandMaster cm;
private BehGraphUndirected behGraph;
#Override
public Object run(BehGraphUndirected behGraph, VisualizationImageServer panel, InterpretMaster interpretMaster, String... args) {
System.out.print("create Runs \n");
this.cm = new CommandMaster();
this.behGraph = behGraph;
if(cm.exists(args[0]))
{
//got to another command
}else
{
switch (args[0]) {
case "node":
this.createNode(args[1]);
break;
case "label":
this.createLabel(args[1]);
break;
}
}
interpretMaster.refreshAndRepaint();
return null;
}
public void createNode(String nodeName)
{
this.behGraph.addVertex(nodeName);
System.out.print("vertex: "+nodeName+" added");
}
private void createLabel(String string) {
}
class str
{
int i;
long j;
}
}
Graph images before and after connecting two nodes:
and Here is my BehGraphUndirected class:
package GraphHandling;
import edu.uci.ics.jung.graph.UndirectedSparseGraph;
import java.util.LinkedList;
/**
*
* #author Administrator
*/
public class BehGraphUndirected extends UndirectedSparseGraph{
private final LinkedList<Node> nodeList;
public BehGraphUndirected()
{
this.nodeList = new LinkedList<>();
}
public void addNode(Node newNode)
{
this.nodeList.add(newNode);
}
}
You should look at what BehGraphUndirected is doing; it's not a JUNG class or interface.
What is the name of the vertex that's being created, and how does that relate to what's being passed to the create method?
I have compiled and tested your code , The Jung library seems working right and It extinguishes the different nodes by the different object that was given to it It seems you have some other problem , Like a problem in processing the input strings that are used as objects that create nodes.

Prevent to read file many times

I am trying to write an i18n app. The program read a json file, that contains translation from languages and it based on json structure.
{
"EN": {
"TEXT1": "Hello",
"TEXT2": "March"
},
"DE": {
"TEXT1": "Hallo",
"TEXT2": "März"
}
}
My program read the json file in async way with the file class, the whole code
import 'dart:io';
import 'dart:async';
import 'package:json_object/json_object.dart';
abstract class I18n {
static _I18n _i18n;
factory I18n(String file, String lang) {
if(_i18n == null) {
_i18n = new _I18n(file, lang);
return _i18n;
}
return _i18n;
}
Future<String> getTextByMap(String textId);
}
class _I18n implements I18n {
File _file;
String _lang;
JsonObject _jsonContainer;
JsonObject _jsonFiltered;
Future<JsonObject> _imme;
// Parameters:
// file: The whole path and filename
// lang: Expected language
_I18n(String file, this._lang) {
this._file = new File(file);
}
// Read file and return the content of file.
Future<String> _readFileFromStream() {
var com = new Completer();
this._file.exists()
.then((fileExists) {
if(!fileExists) {
throw new StateError('File not found');
}
return this._file.readAsString()
.then((stream) => com.complete(stream));
});
return com.future;
}
void _convertContentToJson(String stream) {
this._jsonContainer = new JsonObject.fromJsonString(stream);
}
Future<JsonObject> _prepareData() {
return this._readFileFromStream().then((stream) {
_convertContentToJson(stream);
this._jsonFiltered = this._jsonContainer[this._lang];
return this._jsonFiltered;
});
}
Future<String> getTextByMap(String textId) {
return this._prepareData().then((filterd) {
return filterd[textId];
});
}
}
and the main code
import 'package:i18n/i18n.dart';
void main() {
var i18n = new I18n('../hello.json', 'EN');
i18n.getTextByMap('TEXT1').then((val) => print(val));
i18n.getTextByMap('TEXT2').then((val) => print(val));
}
Everything here, happen in dart async way, read json file etc. And everytime, when i call the method
i18n.getTextByMap('TEXT1').then((val) => print(val));
it gonna read the json file again and again. I tried to rewrite the method to prevent reading json file many times
Future<String> getTextByMap(String textId) {
if(this._jsonFiltered == null)
{
return this._prepareData().then((filterd) {
return filterd[textId];
});
}
return new Future(() => this._jsonFiltered[textId]);
}
but it doesn't work too, because dart works in async way.
My question is, how can i keep this json file content in an object? Read json file only one time and keep the contents in an object, it is better then read json file everytime, that is my opinion.
It could do everything in sync way, then i wouldn't have such as problem but this is not dart terminology.
In which order do dart execute I/O operations, like this?
Future
I/O Events
My solution would be to create a class with a factory constructor. The factory constructor always returns a object of that file.
Your problem is that futures are parallel. So both calls are executed in parallel. The solution is to let the first future complete and then do other stuff to be able to get cached results.
Then you can have a read() method that reads the value of the file if it is not present in the classes "contents" attribute for example - or if that attribute is not null, it loads the file in background.
In both cases a completer or future is returned you can listen on.
EDIT Example Code:
example_async_file_factory.dart
import 'dart:io';
import 'dart:async';
class FileHolder {
String _contents = null;
String path;
static Map<String, FileHolder> _files;
factory FileHolder(String path) {
if (_files == null) {
_files = {};
}
if (_files.containsKey(path)) {
return _files[path];
} else {
final fh = new FileHolder._internal(path);
_files[path] = fh;
return fh;
}
}
FileHolder._internal(this.path);
Future<String> getContents() {
if(_contents != null) {
print("cached");
return new Future.value(_contents);
} else {
print("read");
File f = new File(this.path);
Future<String> future = f.readAsString();
Completer completer = new Completer();
future.then((String c) {
_contents = c;
completer.complete(_contents);
});
return completer.future;
}
}
}
void main() {
FileHolder f = new FileHolder("example_async_file_factory.dart");
f.getContents().then((String contents) {
print(contents.length);
FileHolder f2 = new FileHolder("example_async_file_factory.dart");
f2.getContents().then((String contents) {
print(contents.length);
});
f2.getContents().then((String contents) {
print(contents.length);
});
f.getContents().then((String contents) {
print(contents.length);
});
});
}
Output:
read
1411
cached
cached
cached
1411
1411
1411
Regards
Robert

Creating an instance of a generic type in DART

I was wondering if is possible to create an instance of a generic type in Dart. In other languages like Java you could work around this using reflection, but I'm not sure if this is possible in Dart.
I have this class:
class GenericController <T extends RequestHandler> {
void processRequest() {
T t = new T(); // ERROR
}
}
I tried mezonis approach with the Activator and it works. But it is an expensive approach as it uses mirrors, which requires you to use "mirrorsUsed" if you don't want to have a 2-4MB js file.
This morning I had the idea to use a generic typedef as generator and thus get rid of reflection:
You define a method type like this: (Add params if necessary)
typedef S ItemCreator<S>();
or even better:
typedef ItemCreator<S> = S Function();
Then in the class that needs to create the new instances:
class PagedListData<T>{
...
ItemCreator<T> creator;
PagedListData(ItemCreator<T> this.creator) {
}
void performMagic() {
T item = creator();
...
}
}
Then you can instantiate the PagedList like this:
PagedListData<UserListItem> users
= new PagedListData<UserListItem>(()=> new UserListItem());
You don't lose the advantage of using generic because at declaration time you need to provide the target class anyway, so defining the creator method doesn't hurt.
You can use similar code:
import "dart:mirrors";
void main() {
var controller = new GenericController<Foo>();
controller.processRequest();
}
class GenericController<T extends RequestHandler> {
void processRequest() {
//T t = new T();
T t = Activator.createInstance(T);
t.tellAboutHimself();
}
}
class Foo extends RequestHandler {
void tellAboutHimself() {
print("Hello, I am 'Foo'");
}
}
abstract class RequestHandler {
void tellAboutHimself();
}
class Activator {
static createInstance(Type type, [Symbol constructor, List
arguments, Map<Symbol, dynamic> namedArguments]) {
if (type == null) {
throw new ArgumentError("type: $type");
}
if (constructor == null) {
constructor = const Symbol("");
}
if (arguments == null) {
arguments = const [];
}
var typeMirror = reflectType(type);
if (typeMirror is ClassMirror) {
return typeMirror.newInstance(constructor, arguments,
namedArguments).reflectee;
} else {
throw new ArgumentError("Cannot create the instance of the type '$type'.");
}
}
}
I don't know if this is still useful to anyone. But I have found an easy workaround. In the function you want to initialize the type T, pass an extra argument of type T Function(). This function should return an instance of T. Now whenever you want to create object of T, call the function.
class foo<T> {
void foo(T Function() creator) {
final t = creator();
// use t
}
}
P.S. inspired by Patrick's answer
2022 answer
Just came across this problem and found out that although instantiating using T() is still not possible, you can get the constructor of an object easier with SomeClass.new in dart>=2.15.
So what you could do is:
class MyClass<T> {
final T Function() creator;
MyClass(this.creator);
T getGenericInstance() {
return creator();
}
}
and when using it:
final myClass = MyClass<SomeOtherClass>(SomeOtherClass.new)
Nothing different but looks cleaner imo.
Here's my work around for this sad limitation
class RequestHandler {
static final _constructors = {
RequestHandler: () => RequestHandler(),
RequestHandler2: () => RequestHandler2(),
};
static RequestHandler create(Type type) {
return _constructors[type]();
}
}
class RequestHandler2 extends RequestHandler {}
class GenericController<T extends RequestHandler> {
void processRequest() {
//T t = new T(); // ERROR
T t = RequestHandler.create(T);
}
}
test() {
final controller = GenericController<RequestHandler2>();
controller.processRequest();
}
Sorry but as far as I know, a type parameter cannot be used to name a constructor in an instance creation expression in Dart.
Working with FLutter
typedef S ItemCreator<S>();
mixin SharedExtension<T> {
T getSPData(ItemCreator<T> creator) async {
return creator();
}
}
Abc a = sharedObj.getSPData(()=> Abc());
P.S. inspired by Patrick
simple like that.
import 'dart:mirrors';
void main(List<String> args) {
final a = A<B>();
final b1 = a.getInstance();
final b2 = a.getInstance();
print('${b1.value}|${b1.text}|${b1.hashCode}');
print('${b2.value}|${b2.text}|${b2.hashCode}');
}
class A<T extends B> {
static int count = 0;
T getInstance() {
return reflectClass(T).newInstance(
Symbol(''),
['Text ${++count}'],
{Symbol('value'): count},
).reflectee;
}
}
class B {
final int value;
final String text;
B(this.text, {required this.value});
}
Inspired by Patrick's answer, this is the factory I ended up with.
class ServiceFactory<T> {
static final Map<Type, dynamic> _cache = <String, dynamic>{};
static T getInstance<T>(T Function() creator) {
String typeName = T.toString();
return _cache.putIfAbsent(typeName, () => creator());
}
}
Then I would use it like this.
final authClient = ServiceFactory.getInstance<AuthenticationClient>(() => AuthenticationClient());
Warning: Erik made a very good point in the comment below that the same type name can exist in multiple packages and that will cause issues. As much as I dislike to force the user to pass in a string key (that way it's the consumer's responsibility to ensuring the uniqueness of the type name), that might be the only way.

Importing Triples with Tinkerpop/bluebrints into OrientDB

Im trying to import RDF-Triples into OrientDB with help of tinkerpop/blueprints.
I found the basic usage here.
Im now that far:
import info.aduna.iteration.CloseableIteration;
import org.openrdf.model.Statement;
import org.openrdf.model.ValueFactory;
import org.openrdf.sail.Sail;
import org.openrdf.sail.SailConnection;
import org.openrdf.sail.SailException;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
import com.tinkerpop.blueprints.oupls.sail.GraphSail;
import de.hof.iisys.relationExtraction.jena.parser.impl.ParserStreamIterator;
import de.hof.iisys.relationExtraction.neo4j.importer.Importer;
public class ImporterJenaTriples extends Importer {
private OrientGraph graph = null;
private Sail sail = null;
private SailConnection sailConnection = null;
private ValueFactory valueFactory = null;
private Thread parserThread = null;
public ImporterJenaTriples(ParserStreamIterator parser, String databasePath) throws SailException {
this.parser = parser;
this.databasePath = databasePath;
this.initialize();
}
private void initialize() throws SailException {
this.graph = new OrientGraph(this.databasePath);
this.sail = new GraphSail<OrientGraph>(graph);
sail.initialize();
this.sailConnection = sail.getConnection();
this.valueFactory = sail.getValueFactory();
}
public void startImport() {
this.parserThread = new Thread(this.parser);
this.parserThread.start();
try {
Triple next = (Triple) this.parser.getIterator().next();
Node subject = next.getSubject();
Node predicate = next.getPredicate();
Node object = next.getObject();
} catch (SailException e) {
e.printStackTrace();
}
try {
CloseableIteration<? extends Statement, SailException> results = this.sailConnection.getStatements(null, null, null, false);
while(results.hasNext()) {
System.out.println(results.next());
}
} catch (SailException e) {
e.printStackTrace();
}
}
public void stopImport() throws InterruptedException {
this.parser.terminate();
this.parserThread.join();
}
}
What i need to do now is to differ the types of subject, predicate and object
but the problem is i dont know which types they are and how i have to use
the valuefactory to create the type and to add the Statement to my SailConnection.
Unfortunately i cant find an example how to use it.
Maybe someone has done it before and knows how to continue.
I guess you need to convert from Jena object types to Sesame ones and use the
The unsupported project https://github.com/afs/JenaSesame may have some code for that.
But mixing Jena and Sesame seems to make things more complicated - have you consider using the Sesame parser and getting Sesame objects that can go into the SailConnection?

grails limited table creation

I'd like to use the Grails feature for creating/updating database tables on a limited basis. Specifically, I'd like Grails to manage some tables, but not all.
Is there a way to limit the tables managed by Grails or is it an all or nothing proposition?
In general it's all or nothing since Grails uses Hibernate's HBM2DDL functionality. But you can intercept the process using a custom configuration subclass. Here's an example that extends GrailsAnnotationConfiguration and overrides all three SQL generation methods:
package com.yourcompany.yourapp;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
public class MyConfiguration extends GrailsAnnotationConfiguration {
private static final String[] IGNORE_NAMES = { "foo", "bar" };
#Override
public String[] generateDropSchemaScript(Dialect dialect) throws HibernateException {
return prune(super.generateDropSchemaScript(dialect));
}
#Override
public String[] generateSchemaCreationScript(Dialect dialect) throws HibernateException {
return prune(super.generateSchemaCreationScript(dialect));
}
#Override
public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata)
throws HibernateException {
return prune(super.generateSchemaUpdateScript(dialect, databaseMetadata));
}
private String[] prune(String[] script) {
List<String> pruned = new ArrayList<String>();
for (String command : script) {
for (String ignoreName : IGNORE_NAMES) {
if (!command.toLowerCase().contains(" table " + ignoreName + " ")) {
pruned.add(command);
}
}
}
return pruned.toArray(new String[pruned.size()]);
}
}
You don't need to override all three, e.g. you could let creates go through but remove updates.
This gets registered in grails-app/conf/DataSource.groovy:
dataSource {
pooled = true
driverClassName = ...
username = ...
password = ...
configClass = com.yourcompany.yourapp.MyConfiguration
}
Note that the class has to be written in Java because of an issue with private methods in the base class clashing with methods that Groovy adds to all groovy classes.
Thanks for the fix Steve. I'm reposting the fix above, but formatted for stackoverflow. When I first tried this I missed the fact that the original if (!command.toLowerCase()...) reversed logic in the fix as if (command.toLowerCase()...), which effectively made it look like dbCreate = "create-drop" in my config/DataSource.groovy was having no effect. I even worked from the HTML source from this page to see intended line breaks of the code, but still missed that vital bit of logic :-( Once I got this entered correctly it worked great.
private String[] prune(String[] script) {
List<String> pruned = new ArrayList<String>();
for (String command : script) {
boolean ignore = false;
for (String ignoreName : IGNORE_NAMES) {
if (command.toLowerCase().contains(" table " + ignoreName.toLowerCase() + " ")) {
ignore = true;
break;
}
}
if (!ignore) {
pruned.add(command);
}
}
return pruned.toArray(new String[pruned.size()]);
}

Resources