Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,55 @@ db.query("items", Item.class)
.update();
```

##### serial()
The `serial()` function returns a unique identifier from the sequence of integer for each document in the namespace.
This function can be used in both `INSERT` and `UPDATE` queries.
To use this function, specify the `@Serial` annotation on the field.

```java
public class Item {

@Reindex(name = "id", isPrimaryKey = true)
@Serial(strategy = PreceptApplyStrategy.WHEN_NULL)
private Integer id;

@Reindex(name = "version")
@Serial(strategy = PreceptApplyStrategy.ALWAYS)
private Integer version;

}
```

The `@Serial` annotation has the following strategies to apply the function:
- `WHEN_NULL` - when the field is null, use this strategy when the value must be generated only once (recommended).
- `ALWAYS` - always generates a new value for the field (default if no strategy is specified due to compatibility reasons).

##### Apply precept functions using programmatic precepts API:

```java
ReindexerPrecept idPrecept = ReindexerPrecept.builder()
.fieldPath("id")
.jsonPath("id")
.expression(Expression.serial())
.strategy(PreceptApplyStrategy.WHEN_NULL)
.build();
ReindexerPrecept createdAtPrecept = ReindexerPrecept.builder()
.fieldPath("createdAt")
.jsonPath("createdAt")
.expression(Expression.now())
.strategy(PreceptApplyStrategy.WHEN_NULL)
.build();
ReindexerPrecept updatedAtPrecept = ReindexerPrecept.builder()
.fieldPath("updatedAt")
.jsonPath("updatedAt")
.expression(Expression.now())
.strategy(PreceptApplyStrategy.ALWAYS)
.build();
reindexer.registerPrecept("items", idPrecept);
reindexer.registerPrecept("items", createdAtPrecept);
reindexer.registerPrecept("items", updatedAtPrecept);
```

Notes:
- The returned timestamp represents seconds (or subunits) since the Unix epoch (January 1, 1970)
- Time resolution depends on the specified unit - use `nsec` for maximum precision
Expand Down
40 changes: 27 additions & 13 deletions src/main/java/ru/rt/restream/reindexer/Namespace.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package ru.rt.restream.reindexer;

import java.util.Optional;

/**
* Provides methods for manipulating Reindexer namespace data.
*
Expand All @@ -32,44 +34,56 @@ public interface Namespace<T> {
/**
* Inserts the given item data.
*
* @param item the item data
* @param item the item data
* @return the inserted {@link T} item
*/
void insert(T item);
T insert(T item);

/**
* Inserts the given json-formatted item data
* Inserts the given json-formatted item data.
* Returns the server-generated {@link T} item, which may contain fields not present
* in the input JSON, or {@link Optional#empty()} if the server returns no data.
*
* @param item the json-formatted item data
* @param item the json-formatted item data
* @return the server-generated {@link T} item, or {@link Optional#empty()} if no data was returned
*/
void insert(String item);
Optional<T> insert(String item);

/**
* Inserts or updates the given item data.
*
* @param item the item data
* @param item the item data
* @return the upserted {@link T} item
*/
void upsert(T item);
T upsert(T item);

/**
* Inserts or updates the given json-formatted item data.
* Returns the server-generated {@link T} item, which may contain fields not present
* in the input JSON, or {@link Optional#empty()} if the server returns no data.
*
* @param item the json-formatted item data
* @param item the json-formatted item data
* @return the server-generated {@link T} item, or {@link Optional#empty()} if no data was returned
*/
void upsert(String item);
Optional<T> upsert(String item);

/**
* Updates the given item data.
*
* @param item the item data
* @param item the item data
* @return the updated {@link T} item
*/
void update(T item);
T update(T item);

/**
* Updates the given json-formatted item data.
* Returns the server-generated {@link T} item, which may contain fields not present
* in the input JSON, or {@link Optional#empty()} if the server returns no data.
*
* @param item the json-formatted item data
* @param item the json-formatted item data
* @return the server-generated {@link T} item, or {@link Optional#empty()} if no data was returned
*/
void update(String item);
Optional<T> update(String item);

/**
* Deletes the given item data.
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/ru/rt/restream/reindexer/PreceptApplyStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2020-present Restream
*
* Licensed 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 ru.rt.restream.reindexer;

/**
* Precept apply strategy.
*/
public enum PreceptApplyStrategy {

/**
* Apply precept always.
*/
ALWAYS,

/**
* Apply precept only when the field is {@literal null}.
*/
WHEN_NULL

}
97 changes: 17 additions & 80 deletions src/main/java/ru/rt/restream/reindexer/QueryResultIterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ public T next() {
}

private <S> S readItem(ItemReader<S> reader, Query<?> queryContext) {
ItemParams params = readItemParams();
Query<?> itemQueryContext = getItemQueryContext(queryContext, params.nsId);
QueryResult.ItemParams params = readItemParams();
Query<?> itemQueryContext = getItemQueryContext(queryContext, params.getNsId());
S item = readItemData(params, reader);
readJoinedItems(item, itemQueryContext, params.nsId);
readJoinedItems(item, itemQueryContext, params.getNsId());
return item;
}

Expand All @@ -149,10 +149,10 @@ private Query<?> getItemQueryContext(Query<?> defaultQueryContext, int nsId) {
return defaultQueryContext;
}

private <S> S readItemData(ItemParams params, ItemReader<S> reader) {
if (params.cptr != 0) {
ByteBuffer nativeBuffer = NativeUtils.getNativeBuffer(queryResult.getResultsPtr(), params.cptr,
params.nsId);
private <S> S readItemData(QueryResult.ItemParams params, ItemReader<S> reader) {
if (params.getCptr() != 0) {
ByteBuffer nativeBuffer = NativeUtils.getNativeBuffer(queryResult.getResultsPtr(), params.getCptr(),
params.getNsId());
return reader.readItem(nativeBuffer);
}

Expand Down Expand Up @@ -210,7 +210,7 @@ private void readJoinedItemsV1(Object item, int nsId) {
CjsonItemReader<?> joinedItemReader = newItemReader(joinedNamespace.getItemClass(), joinedNamespace);
List<Object> subItems = new ArrayList<>(itemsCount);
for (int j = 0; j < itemsCount; j++) {
ItemParams subItemParams = readItemParams();
QueryResult.ItemParams subItemParams = readItemParams();
subItems.add(readItemData(subItemParams, joinedItemReader));
}

Expand All @@ -230,19 +230,19 @@ private void readJoinedItemsV1(Object item, int nsId) {

private void skipJoinedItems(int itemsCount) {
for (int i = 0; i < itemsCount; i++) {
ItemParams itemParams = readItemParams();
if (itemParams.cptr == 0) {
QueryResult.ItemParams itemParams = readItemParams();
if (itemParams.getCptr() == 0) {
int length = (int) buffer.getUInt32();
buffer.skip(length);
}
readJoinedItems(null, null, itemParams.nsId);
readJoinedItems(null, null, itemParams.getNsId());
}
}

private void skipJoinedItemsV1(int itemsCount) {
for (int i = 0; i < itemsCount; i++) {
ItemParams itemParams = readItemParams();
if (itemParams.cptr == 0) {
QueryResult.ItemParams itemParams = readItemParams();
if (itemParams.getCptr() == 0) {
int length = (int) buffer.getUInt32();
buffer.skip(length);
}
Expand Down Expand Up @@ -312,42 +312,12 @@ private void writeJoinResult(Object item, String fieldName, List<Object> subItem
}
}

private ItemParams readItemParams() {
ItemParams params = new ItemParams();

if (queryResult.isWithItemId()) {
params.id = buffer.getVarUInt();
params.version = buffer.getVarUInt();
}

if (queryResult.isWithNsId()) {
params.nsId = (int) buffer.getVarUInt();
}

private QueryResult.ItemParams readItemParams() {
QueryResult.ItemParams itemParams = queryResult.readItemParams();
if (queryResult.isWithRank()) {
//used for full-text search
if (queryResult.getRankFormat() == 0) {
params.rank = buffer.getFloat();
currentRank = params.rank;
} else {
params.rank = buffer.getVarUInt();
}
currentRank = itemParams.getRank();
}

if (queryResult.isWithShardId()) {
if (queryResult.getShardId() != Consts.SHARDING_PROXY_OFF) {
params.shardId = queryResult.getShardId();
} else {
params.shardId = (int) buffer.getVarUInt();
}

}

if (queryResult.isWithResultsPtr()) {
params.cptr = buffer.getUInt64();
}

return params;
return itemParams;
}

private boolean needFetch() {
Expand Down Expand Up @@ -395,37 +365,4 @@ public void close() {
closed = true;
}

private static class ItemParams {
private float rank = -1;
private long id = -1;
private int shardId = Consts.SHARDING_PROXY_OFF;
private long version = -1;
private long cptr;
private int nsId = 0;

public float getRank() {
return rank;
}

public long getId() {
return id;
}

public int getShardId() {
return shardId;
}

public long getVersion() {
return version;
}

public long getCptr() {
return cptr;
}

public int getNsId() {
return nsId;
}
}

}
Loading
Loading