@Test
  public void fulltext() throws Exception {
    final Node node =
        createNode(
            CreateNodeParams.create()
                .name("my-node-1")
                .parent(NodePath.ROOT)
                .indexConfigDocument(
                    PatternIndexConfigDocument.create()
                        .analyzer(NodeConstants.DOCUMENT_INDEX_DEFAULT_ANALYZER)
                        .defaultConfig(IndexConfig.BY_TYPE)
                        .build())
                .build());

    final NodeQuery query =
        NodeQuery.create()
            .query(
                QueryExpr.from(
                    new DynamicConstraintExpr(
                        FunctionExpr.from(
                            "fulltext",
                            ValueExpr.string(NodeIndexPath.NAME.getPath()),
                            ValueExpr.string("My node name is my-node-1"),
                            ValueExpr.string("OR")))))
            .build();

    final FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(1, result.getNodes().getSize());
    assertNotNull(result.getNodes().getNodeById(node.id()));
  }
  private void queryAndAssert(final Node node, final String queryString, final int expected) {
    final NodeQuery query = NodeQuery.create().query(QueryParser.parse(queryString)).build();

    final FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(expected, result.getNodes().getSize());
    assertNotNull(result.getNodes().getNodeById(node.id()));
  }
  @Test
  public void negate() throws Exception {
    final PropertyTree data = new PropertyTree();
    data.addString("title", "fisk kake");

    final Node node =
        createNode(
            CreateNodeParams.create()
                .name("my-node-1")
                .parent(NodePath.ROOT)
                .data(data)
                .indexConfigDocument(
                    PatternIndexConfigDocument.create()
                        .analyzer(NodeConstants.DOCUMENT_INDEX_DEFAULT_ANALYZER)
                        .defaultConfig(IndexConfig.BY_TYPE)
                        .build())
                .build());

    final PropertyTree data2 = new PropertyTree();
    data2.addString("title", "fisk båt");

    createNode(
        CreateNodeParams.create()
            .name("my-node-2")
            .parent(NodePath.ROOT)
            .data(data2)
            .indexConfigDocument(
                PatternIndexConfigDocument.create()
                    .analyzer(NodeConstants.DOCUMENT_INDEX_DEFAULT_ANALYZER)
                    .defaultConfig(IndexConfig.BY_TYPE)
                    .build())
            .build());

    final NodeQuery query =
        NodeQuery.create()
            .query(
                QueryExpr.from(
                    new DynamicConstraintExpr(
                        FunctionExpr.from(
                            "fulltext",
                            ValueExpr.string("title"),
                            ValueExpr.string("fisk -båt"),
                            ValueExpr.string("AND")))))
            .build();

    final FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(1, result.getNodes().getSize());
    assertNotNull(result.getNodes().getNodeById(node.id()));
  }
  FindContentIdsByQueryResult execute() {
    final NodeQuery nodeQuery =
        ContentQueryNodeQueryTranslator.translate(this.query)
            .addQueryFilters(createFilters())
            .build();

    final FindNodesByQueryResult result = nodeService.findByQuery(nodeQuery);

    return FindContentIdsByQueryResult.create()
        .contents(ContentNodeHelper.toContentIds(result.getNodeIds()))
        .aggregations(result.getAggregations())
        .hits(result.getHits())
        .totalHits(result.getTotalHits())
        .build();
  }
  @Test
  public void fulltext_with_path() throws Exception {

    final PropertyTree data = new PropertyTree();

    final String path1 = "test.of.string.with.path";
    final String value1 = "fisk ost pølse løk";
    data.setString(path1, value1);

    final String path2 = "mystring.with.path2";
    final String value2 = "vif rbk lsk sif";
    data.setString(path2, value2);

    final Node node =
        createNode(
            CreateNodeParams.create()
                .name("fisk ost")
                .parent(NodePath.ROOT)
                .data(data)
                .indexConfigDocument(
                    PatternIndexConfigDocument.create()
                        .analyzer(NodeConstants.DOCUMENT_INDEX_DEFAULT_ANALYZER)
                        .defaultConfig(IndexConfig.BY_TYPE)
                        .build())
                .build());

    final NodeQuery query =
        NodeQuery.create()
            .query(
                QueryExpr.from(
                    new DynamicConstraintExpr(
                        FunctionExpr.from(
                            "fulltext",
                            ValueExpr.string(path1),
                            ValueExpr.string("leter etter fisk"),
                            ValueExpr.string("OR")))))
            .build();

    final FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(1, result.getNodes().getSize());
    assertNotNull(result.getNodes().getNodeById(node.id()));
  }
  FindContentByQueryResult execute() {
    final NodeQuery nodeQuery =
        ContentQueryNodeQueryTranslator.translate(this.params.getContentQuery())
            .addQueryFilters(createFilters())
            .build();

    final FindNodesByQueryResult result = nodeService.findByQuery(nodeQuery);

    final NodeIds nodeIds = result.getNodeIds();

    final Nodes foundNodes = this.nodeService.getByIds(nodeIds);

    Contents contents = this.translator.fromNodes(foundNodes, true);

    return FindContentByQueryResult.create()
        .contents(contents)
        .aggregations(result.getAggregations())
        .hits(result.getHits())
        .totalHits(result.getTotalHits())
        .build();
  }
  @Test
  public void ranges_with_date_math_date() throws Exception {
    final Instant anchor = Instant.parse("2014-12-10T10:00:00Z");

    createNode(anchor, "n1", NodePath.ROOT);
    createNode(anchor.plusSeconds(-3600), "n2", NodePath.ROOT);
    createNode(anchor.plusSeconds(-3600 * 2), "n3", NodePath.ROOT);
    createNode(anchor.plusSeconds(-3600 * 3), "n4", NodePath.ROOT);
    createNode(anchor.plusSeconds(-3600 * 4), "n5", NodePath.ROOT);
    createNode(anchor.plusSeconds(-3600 * 5), "n6", NodePath.ROOT);

    final NodeQuery query =
        NodeQuery.create()
            .addAggregationQuery(
                DateRangeAggregationQuery.create("myDateRange")
                    .fieldName("instant")
                    .addRange(DateRange.create().to("2014-12-10T10:00:00Z||-5h").build())
                    .addRange(
                        DateRange.create()
                            .from("2014-12-10T10:00:00.000Z||-5h")
                            .to("2014-12-10T10:00:00.000Z||-3h")
                            .build())
                    .addRange(DateRange.create().from("2014-12-10T10:00:00Z||-3h").build())
                    .build())
            .build();

    FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(1, result.getAggregations().getSize());

    final BucketAggregation aggregation =
        (BucketAggregation) result.getAggregations().get("myDateRange");

    final Buckets buckets = aggregation.getBuckets();

    final Iterator<Bucket> iterator = buckets.iterator();
    verifyBucket(iterator.next(), 0);
    verifyBucket(iterator.next(), 2);
    verifyBucket(iterator.next(), 4);
  }
  @Test
  public void ranges() throws Exception {
    createNode(Instant.parse("2014-12-10T10:00:00Z"), "n1", NodePath.ROOT);
    createNode(Instant.parse("2014-12-10T10:30:00Z"), "n2", NodePath.ROOT);
    createNode(Instant.parse("2014-12-10T11:30:00Z"), "n3", NodePath.ROOT);
    createNode(Instant.parse("2014-12-10T12:45:00Z"), "n4", NodePath.ROOT);
    createNode(Instant.parse("2014-12-10T13:59:59Z"), "n5", NodePath.ROOT);
    createNode(Instant.parse("2014-12-10T14:01:00Z"), "n6", NodePath.ROOT);

    final NodeQuery query =
        NodeQuery.create()
            .addAggregationQuery(
                DateRangeAggregationQuery.create("myDateRange")
                    .fieldName("instant")
                    .addRange(DateRange.create().to(Instant.parse("2014-12-10T11:00:00Z")).build())
                    .addRange(
                        DateRange.create()
                            .from(Instant.parse("2014-12-10T11:00:00Z"))
                            .to(Instant.parse("2014-12-10T14:00:00Z"))
                            .build())
                    .addRange(
                        DateRange.create().from(Instant.parse("2014-12-10T14:00:00Z")).build())
                    .build())
            .build();

    FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(1, result.getAggregations().getSize());

    final BucketAggregation aggregation =
        (BucketAggregation) result.getAggregations().get("myDateRange");

    final Buckets buckets = aggregation.getBuckets();

    final Iterator<Bucket> iterator = buckets.iterator();
    verifyBucket(iterator.next(), 2);
    verifyBucket(iterator.next(), 3);
    verifyBucket(iterator.next(), 1);
  }
  @Test
  public void fulltext_norwegian_characters() throws Exception {
    final PropertyTree data = new PropertyTree();
    data.addString("myProperty", "æ");
    final PropertySet userdata = data.addSet("data");
    userdata.addString("displayName", "ø å");

    final Node node =
        createNode(
            CreateNodeParams.create()
                .name("my-node-1")
                .parent(NodePath.ROOT)
                .data(data)
                .indexConfigDocument(
                    PatternIndexConfigDocument.create()
                        .analyzer(NodeConstants.DOCUMENT_INDEX_DEFAULT_ANALYZER)
                        .defaultConfig(IndexConfig.BY_TYPE)
                        .build())
                .build());

    refresh();

    printContentRepoIndex();

    final NodeQuery query =
        NodeQuery.create()
            .query(
                QueryExpr.from(
                    new DynamicConstraintExpr(
                        FunctionExpr.from(
                            "fulltext",
                            ValueExpr.string(NodeIndexPath.ALL_TEXT.getPath()),
                            ValueExpr.string("æ"),
                            ValueExpr.string("OR")))))
            .build();

    final FindNodesByQueryResult result = doFindByQuery(query);

    assertEquals(1, result.getNodes().getSize());
    assertNotNull(result.getNodes().getNodeById(node.id()));

    final NodeQuery query2 =
        NodeQuery.create()
            .query(
                QueryExpr.from(
                    new DynamicConstraintExpr(
                        FunctionExpr.from(
                            "fulltext",
                            ValueExpr.string("data.displayName"),
                            ValueExpr.string("ø å"),
                            ValueExpr.string("OR")))))
            .build();

    final FindNodesByQueryResult result2 = doFindByQuery(query2);

    assertEquals(1, result2.getNodes().getSize());
    assertNotNull(result2.getNodes().getNodeById(node.id()));
  }