Asynchronous OrientDB异步执行脚本并以惰性方式获取记录
目前,我们正在OrientDB 2.2版中使用文档API。假设我们有一个阶级公司和一个阶级雇员。假设我们对所有公司感兴趣,其中至少有一名员工的名字来自任意列表。在我们的公司架构中,员工被定义为LinkedList。 我们的查询看起来像这样:Asynchronous OrientDB异步执行脚本并以惰性方式获取记录,asynchronous,lazy-loading,orientdb,orientdb2.2,Asynchronous,Lazy Loading,Orientdb,Orientdb2.2,目前,我们正在OrientDB 2.2版中使用文档API。假设我们有一个阶级公司和一个阶级雇员。假设我们对所有公司感兴趣,其中至少有一名员工的名字来自任意列表。在我们的公司架构中,员工被定义为LinkedList。 我们的查询看起来像这样: select from Company where employees in (select from Employee where name in ["John", "Paul"]) select from Company let $e = select
select from Company where employees in (select from Employee where name in ["John", "Paul"])
select from Company let $e = select from employees where name in ["John", "Paul"] where employees in $e
目前我们定义了以下两个索引:
Company.employees(员工链接上的索引(其@rid))->字典哈希索引和
Employee.name->notunique索引
使用explain执行上述查询时,我们看到只使用了第二个索引Employee.name,因为我们没有将上述索引定义为复合索引。据我所知,Orient 2.x不支持跨不同类的复合索引,比如我们的例子。
类似这样的查询:
select from Company where employees in (select from Employee where name in ["John", "Paul"])
select from Company let $e = select from employees where name in ["John", "Paul"] where employees in $e
也不要解决我们的问题
在不同的博客上搜索发现了两条建议:
public class OCommandAsyncScript extends OCommandScript implements OCommandRequestAsynch{
public OCommandAsyncScript(String sql, String cmd) {
super(sql, cmd);
}
@Override
public boolean isAsynchronous() {
return true;
}
private void containsAtLeastOne(final @Nonnull ODatabaseDocumentTx documentTx,
final @Nonnull Consumer<Company> matchConsumer,
final @Nonnull String queryText
) throws TimeoutException {
String cmd = "begin\n";
cmd += "let a = select from Employee where name " + queryText + "\n";
cmd += "let b = select from Company where employees in $a\n";
cmd += "COMMIT\n";
cmd += "return $b";
final OCommandHandler resultListener = new OCommandHandler(documentTx, (document -> {
final Company companies = document2model(document);
matchConsumer.accept(company);
}));
OCommandAsyncScript request = new OCommandAsyncScript("sql", cmd);
request.setResultListener(resultListener);
documentTx.command(request).execute();
...
}
}
public class OCommandHandler implements OCommandResultListener {
private final ODatabaseDocumentTx database;
private final Consumer<ODocument> matchConsumer;
public OCommandHandler(
final @Nonnull ODatabaseDocumentTx database,
final @Nonnull Consumer<ODocument> matchConsumer
) {
this.database = database;
this.matchConsumer = matchConsumer;
}
@Override
public boolean result(Object iRecord) {
if (iRecord != null) {
final ODocument document = (ODocument) iRecord;
/*
Result handler might be asynchronous, if document is loaded in a lazy mode,
database will be queries to fetch various fields. Need to activate it on the current thread.
*/
database.activateOnCurrentThread();
matchConsumer.accept(document);
}
return true;
}
...
}
公共类OCommandAsyncScript扩展了OCommandScript实现了OCommandRequestAsynch{
公共OCommandAsyncScript(字符串sql、字符串cmd){
super(sql,cmd);
}
@凌驾
公共布尔同步(){
返回true;
}
私有void containsAtLeastOne(最终@Nonnull ODatabaseDocumentTx documentTx,
最终@Nonnull Consumer matchConsumer,
final@Nonnull字符串queryText
)抛出TimeoutException{
String cmd=“begin\n”;
cmd+=“让a=从名为“+queryText+”\n”的员工中选择;
cmd+=“让b=从员工所在的公司中选择$a\n”;
cmd+=“提交\n”;
cmd+=“返回$b”;
最终OCommandHandler resultListener=新的OCommandHandler(documentTx,(文档->{
最终公司=文件2模型(文件);
匹配消费者。接受(公司);
}));
OCommandAsyncScript请求=新的OCommandAsyncScript(“sql”,cmd);
setResultListener(resultListener);
documentTx.command(request.execute();
...
}
}
公共类OCommandHandler实现OCommandResultListener{
专用最终ODatabaseDocumentTx数据库;
私人最终消费者;
公共命令处理程序(
最终@Nonnull ODatabaseDocumentTx数据库,
最终@Nonnull使用者匹配使用者
) {
this.database=数据库;
this.matchConsumer=matchConsumer;
}
@凌驾
公共布尔结果(对象iRecord){
如果(iRecord!=null){
最终气味文件=(气味文件)i记录;
/*
如果文档以惰性模式加载,则结果处理程序可能是异步的,
数据库将被查询以获取各种字段。需要在当前线程上激活它。
*/
database.activateOnCurrentThread();
matchConsumer.accept(文档);
}
返回true;
}
...
}
不幸的是,定义自定义OCommandAsyncScript的方法不起作用。调试Orient的OStorageRemote类时,似乎无法读取部分结果,以下是源代码的相应摘录:
public Object command(final OCommandRequestText iCommand) {
....
try {
OStorageRemote.this.beginResponse(network, session);
List<ORecord> temporaryResults = new ArrayList();
boolean addNextRecord = true;
byte status;
if(asynch) {
while((status = network.readByte()) > 0) {
ORecord record = (ORecord)OChannelBinaryProtocol.readIdentifiable(network);
if(record != null) {
switch(status) {
case 1:
if(addNextRecord) {
addNextRecord = iCommand.getResultListener().result(record);
database.getLocalCache().updateRecord(record);
}
break;
case 2:
if(record.getIdentity().getClusterId() == -2) {
temporaryResults.add(record);
}
database.getLocalCache().updateRecord(record);
}
}
}
}
}
公共对象命令(最终OCommandRequestText iCommand){
....
试一试{
OStorageRemote.this.beginResponse(网络、会话);
List temporaryResults=新建ArrayList();
布尔addNextRecord=true;
字节状态;
如果(异步){
而((status=network.readByte())>0){
ORecord记录=(ORecord)OChannelBinaryProtocol.readIdentification(网络);
if(记录!=null){
开关(状态){
案例1:
如果(添加下一条记录){
addNextRecord=iCommand.getResultListener().result(记录);
database.getLocalCache().updateRecord(记录);
}
打破
案例2:
if(record.getIdentity().getClusterId()=-2){
临时结果。添加(记录);
}
database.getLocalCache().updateRecord(记录);
}
}
}
}
}
Network.readbyte()始终为空,因此无法提取任何记录
还有其他解决方法吗?我们如何在异步模式下执行sql脚本,并以惰性方式检索结果,以防止在应用程序端生成大型列表