From 6a702ee16bf1b3bf2fda9509956c609b751b2c35 Mon Sep 17 00:00:00 2001 From: Joel Bernstein Date: Mon, 8 Oct 2018 12:53:23 -0400 Subject: [PATCH] SOLR-12840: Add pairSort Stream Evaluator --- .../org/apache/solr/client/solrj/io/Lang.java | 1 + .../solrj/io/eval/PairSortEvaluator.java | 93 +++++++++++++++++++ .../apache/solr/client/solrj/io/TestLang.java | 2 +- .../solrj/io/stream/MathExpressionTest.java | 32 +++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairSortEvaluator.java diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/Lang.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/Lang.java index 28c4c66be26..75131ca1508 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/Lang.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/Lang.java @@ -270,6 +270,7 @@ public class Lang { .withFunctionName("getCenter", GetCenterEvaluator.class) .withFunctionName("getRadius", GetRadiusEvaluator.class) .withFunctionName("getSupportPoints", GetSupportPointsEvaluator.class) + .withFunctionName("pairSort", PairSortEvaluator.class) // Boolean Stream Evaluators .withFunctionName("and", AndEvaluator.class) diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairSortEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairSortEvaluator.java new file mode 100644 index 00000000000..17747558792 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairSortEvaluator.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.client.solrj.io.eval; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.Collections; + +import org.apache.solr.client.solrj.io.stream.expr.StreamExpression; +import org.apache.solr.client.solrj.io.stream.expr.StreamFactory; + +public class PairSortEvaluator extends RecursiveNumericEvaluator implements TwoValueWorker { + protected static final long serialVersionUID = 1L; + + public PairSortEvaluator(StreamExpression expression, StreamFactory factory) throws IOException{ + super(expression, factory); + } + + @Override + public Object doWork(Object first, Object second) throws IOException{ + if(null == first){ + throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - null found for the first value",toExpression(constructingFactory))); + } + if(null == second){ + throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - null found for the second value",toExpression(constructingFactory))); + } + if(!(first instanceof List)){ + throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - found type %s for the first value, expecting a list of numbers",toExpression(constructingFactory), first.getClass().getSimpleName())); + } + if(!(second instanceof List)){ + throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - found type %s for the second value, expecting a list of numbers",toExpression(constructingFactory), first.getClass().getSimpleName())); + } + + List l1 = (List)first; + List l2 = (List)second; + + if(l2.size() != l1.size()){ + throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - first list (%d) has a different size than the second list (%d)",toExpression(constructingFactory), l1.size(), l2.size())); + } + + List pairs = new ArrayList(); + for(int idx = 0; idx < l1.size(); ++idx){ + double[] pair = new double[2]; + pair[0]= l1.get(idx).doubleValue(); + pair[1] = l2.get(idx).doubleValue(); + pairs.add(pair); + } + + Collections.sort(pairs, new PairComp()); + double[][] data = new double[2][pairs.size()]; + for(int i=0; i { + public int compare(double[] a, double[] b) { + if(a[0] > b[0]) { + return 1; + } else if(a[0] < b[0]) { + return -1; + } else { + if(a[1] > b[1]) { + return 1; + } else if(a[1] < b[1]){ + return -1; + } else { + return 0; + } + } + } + } +} diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/TestLang.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/TestLang.java index 3ae5547fb25..85ddd937a06 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/io/TestLang.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/TestLang.java @@ -73,7 +73,7 @@ public class TestLang extends LuceneTestCase { "outliers", "stream", "getCache", "putCache", "listCache", "removeCache", "zscores", "latlonVectors", "convexHull", "getVertices", "getBaryCenter", "getArea", "getBoundarySize","oscillate", "getAmplitude", "getPhase", "getAngularFrequency", "enclosingDisk", "getCenter", "getRadius", - "getSupportPoints"}; + "getSupportPoints", "pairSort"}; @Test public void testLang() { diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/MathExpressionTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/MathExpressionTest.java index deb4522760f..a095dd89076 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/MathExpressionTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/MathExpressionTest.java @@ -1154,6 +1154,38 @@ public class MathExpressionTest extends SolrCloudTestCase { assertTrue(out.get(5).doubleValue() == 500.23D); } + @Test + public void testPairSort() throws Exception { + String cexpr = "let(a=array(4.5, 7.7, 2.1, 2.1, 6.3)," + + " b=array(1, 2, 3, 4, 5)," + + " c=pairSort(a, b))"; + ModifiableSolrParams paramsLoc = new ModifiableSolrParams(); + paramsLoc.set("expr", cexpr); + paramsLoc.set("qt", "/stream"); + String url = cluster.getJettySolrRunners().get(0).getBaseUrl().toString()+"/"+COLLECTIONORALIAS; + TupleStream solrStream = new SolrStream(url, paramsLoc); + StreamContext context = new StreamContext(); + solrStream.setStreamContext(context); + List tuples = getTuples(solrStream); + assertTrue(tuples.size() == 1); + List> out = (List>)tuples.get(0).get("c"); + System.out.println("###### out:"+out); + assertEquals(out.size(), 2); + List row1 = out.get(0); + assertEquals(row1.get(0).doubleValue(), 2.1, 0); + assertEquals(row1.get(1).doubleValue(), 2.1, 0); + assertEquals(row1.get(2).doubleValue(), 4.5, 0); + assertEquals(row1.get(3).doubleValue(), 6.3, 0); + assertEquals(row1.get(4).doubleValue(), 7.7, 0); + + List row2 = out.get(1); + assertEquals(row2.get(0).doubleValue(), 3, 0); + assertEquals(row2.get(1).doubleValue(), 4, 0); + assertEquals(row2.get(2).doubleValue(), 1, 0); + assertEquals(row2.get(3).doubleValue(), 5, 0); + assertEquals(row2.get(4).doubleValue(), 2, 0); + } + @Test public void testOnes() throws Exception {