Apache Solr. Filtered query results by term occurrences in certain fields.

На текущем проекте для полнотекстового поиска используется Apache Solr. Для взаимодействия с solr используется гем Sunspot.

Была поставлена задача: в результатах поиска выводить только те результаты, в которых запрос содержится более чем один раз в определенных полях. В моем случае это было два поля. Была составлена вот такая табличка с соответствиями:

Поле1

Поле2

Результат

слово не попадает
слово не попадает
слово слово попадает
слово слово попадает
слово слово попадает

Для решения я добавил function query. Sunspot рекомендует делать это так:

Post.search do
  adjust_solr_params do |params|
    params[:q] = "{!lucene q.op=AND df=title} bob"
  end
end

Соответственно я добавил function query для фильтрации поисковых результатов:

params[:fq] = ["type:MyModel","{!frange l=2}{!func}sum(termfreq(field1_text,'#{search_query}'),termfreq(field2_text,'#{search_query}'))"]
Реклама

Inspections for IntelliJ IDEA.

IntelliJ IDEA это такая среда для разработки приложений, разработанная JetBrains. Очень удобная, со многими плюшками. Одна из таких вкусностей это инспекции.  (Settings -> Editor -> Inspections) вот тут можно познакомиться с ними поближе. Инспекция это механизм который проверяет ваш код на соответствие какому-либо условию, подчеркивает (выделяет) тот участок кода который по ее мнению неверный, и даже может предложить варианты решения проблемы. К примеру если вот написать такой код:

String s;
System.out.print(s);

То тут же сработает инспекция, подчеркнет красным, и сообщит что возможно переменная не иницииализированна.
Собственно слово Intelligent в названии IDE, умная, это вот из-за наличия инспекций которые проверяют ваш код.

Собеседование. Exceptions

Был на собеседовании. Вот решил разобрать вопросы на которые не смог ответить.

Что будет происходить в этом участке кода?

...
try{
return null;
}
finally{
return "one";
}

Я считаю будет возвращена строка «one». Т.к. блок  finally выполняется перед return в блоке try.

Каким образом можно пропустить выполнение блока finally?

Тут я ответил что возможность есть ,но как именно, не помню. Вот чтобы в следующий раз помнить. Есть 2 варианта, либо прервать выполнение программы System.exit(0), либо еще этот блок не выполнится если закончит свою работу демонизированная нить:

public class Test {

static class tryMe implements Runnable {
public void run() {
try {
System.out.println("Inside thread");
Thread.sleep(4000);
return;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Thread is dead baby.");
}
}
}

public static void main(String[] args) {
Thread thread = new Thread(new tryMe());
System.out.println("start");
thread.setDaemon(true);
thread.start();
System.out.println("end");
}
}

Проект для резюме.

Эта статья по поводу вечного джуниорского вопроса =) Где взять опыт работы, если опыта нет, а на работу берут только с опытом. Вот мой опыт.
Так получилось что у меня есть ментор. Это человек который может помочь советом, проревьюить код, если в хорошем настроении =) рассказать что-то новое.
И вот какое-то время назад он рассказал про один проект. OrientDB — это opensource графическая NOSQL база данных, интересная очень штука. Но конкретно OrientDB позиционирует себя как очень быстрая база, а еще у нее есть клевый графический модуль, еще она поддерживает blueprints. Поддержка вершин (vertex) и ребер (edge). И в частности про ETL процессор. Это такой тулз, который принимает на вход различные файлы с данными, и конвертит их в базу.
У него возникли проблемы с трансформацией из CSV файла. Предложил нам покрыть его тестами, и провести реформат кода. Тесты писались в JUnit. За основу для написания тестов была взята документация непосредственно из OrientDB и из RFC 4180. В ходе покрытия тестами было выявлено несколько багов. К примеру вот баг с представлением отрицательного числа как строки. Вот еще такой баг,

согласно RFC 418
(6. Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes. For example:
"aaa","b CRLF bb","ccc" CRLF
zzz,yyy,xxx )

тоесть если внутри двойных кавычек есть CRLF, то это всеравно одно строковое поле.

Вот еще такое issue о неправильной обработке null в значении поля. Ну и конечно реформатирование кода.
В результате наш CSV трансформер более или менее работоспособен. Но конечно доделывать его еще надо. Изучен фреймворк JUnit3,JUnit4. Изучена работа с GitHub. Немного просмотрены внутренности этой DB. Получена куча фана.Теперь я контрибъютор в большом проекте.

Тестовое задание.

Поиски работы, рассылания резюме, дали результат в виде того что мне прислали тестовое задание. Вот задание которые вызвало трудности.

Задан отсортированный в алфавитном порядке массив слов, состоящих из символов латинкого алфавита в нижнем регистре (a-z). Необходимо опредделить наибольшее по длинне составное слово в массиве. Под «составным» подразумевается слово, полностью сконструированное из других слов данного массива, при помощи конткатенации.
К примеру для массива [«five», «fivetwo», «fourfive», «fourfivetwo», «one», «onefiveone», «two», «twofivefourone»] ответом будет слово «fourfivetwo» с 11 буквами.

Был написан такой тест:

public static String[] sortedByAlphabetArray = {"five", "fivetwo", "fourfive", "fourfivetwo", "one", "onefiveone", "two", "twofivefourone"};
@Test
public void testGetMaxCompositeWord() throws Exception {
String exp = "fourfivetwo";
String act = new Exercise3().getMaxComplexWord(sortedByAlphabetArray);
assertEquals(exp, act);
}

И по размышлении такой вот код для теста:

public String getMaxComplexWord(String[] sortedByAlphabetArray) {
        List<String> list = new ArrayList<String>(Arrays.asList(sortedByAlphabetArray));
        StringBuilder maxComplexWord = new StringBuilder("");
        for (int i = 0; i < list.size(); i++) {
            if (isComplexWord(list.get(i)) && list.get(i).length() > maxComplexWord.length())
                maxComplexWord = new StringBuilder(list.get(i));
        }
        return maxComplexWord.toString();
    }

    /**
     * Check is given word are ComplexWord
     *
     * @param word
     * @return true or false
     */
    public boolean isComplexWord(String word) {
        boolean ret = false;
        List<String> list = new ArrayList<String>(Arrays.asList(sortedByAlphabetArray));
        Iterator itr = list.iterator();
        while (itr.hasNext()) {
            String substring = (String) itr.next();
            if (substring.length() >= word.length() || !word.contains(substring)) itr.remove();
        }
        Integer sumSubstringLength = 0;
        for (int i = 0; i < list.size(); i++) sumSubstringLength += list.get(i).length();
        if (word.length() <= sumSubstringLength) return true;
        return ret;
    }

Но у меня такое чувство что как-то некрасиво все. =(

Статья Martin Fawler — Continuous Integration, Yegor Boyarenko — Why Continuous Integration Doesn’t Work

Прикольная статья.
http://www.martinfowler.com/articles/continuousIntegration.html

Вот достаточно новая статья о CI, плюс к ней продолжение.
http://devops.com/blogs/continuous-integration-doesnt-work/
продолжение:
http://www.yegor256.com/2014/10/08/continuous-integration-is-dead.html

Идея ок. Тоесть Yegor Bugayenko предлагает ввести правило: коммит попадает в мастер, только тогда, когда он прошел проверку.
Таким образом у нас всегда будет рабочий билд. Плюс это должно мотивировать программиста на траблшутинг своего кода.
На мой взгляд это одно из проявлений принципа loose coupling. Вставляя проверку на прохождение тестов уменьшается вероятность возникновения неработающего билда. Короче говоря фильтр. И тут же предлагается решение =) свой CI с блекджеком и шлюхами, который предложенный функционал и реализует Rultor.
Мне нравится такой подход. Обозначение проблемы и преджложение решения. Конструктивно.
Но мне кажется что есстесственным образом эта проблема должна решаться силами тимлида, он должен чекать и направлять работников при необходимости =) А то что никому в реальности CI не нравится, так это звериный оскал капитализма.