Skip to content

Commit 7ac879c

Browse files
authored
Merge pull request #1592 from multiversx/fix-elastic-searching-timeframe
fix elastic searching
2 parents 58eae3e + d9020a5 commit 7ac879c

File tree

2 files changed

+57
-63
lines changed

2 files changed

+57
-63
lines changed

src/common/indexer/elastic/elastic.indexer.helper.ts

Lines changed: 39 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,7 @@ export class ElasticIndexerHelper {
9999
));
100100
}
101101

102-
if (filter.before || filter.after) {
103-
if (filter.before) {
104-
const timestampBeforeIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
105-
elasticQuery = elasticQuery.withRangeFilter(timestampBeforeIdentifier, new RangeLowerThanOrEqual(filter.before));
106-
}
107-
if (filter.after) {
108-
const timestampAfterIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
109-
elasticQuery = elasticQuery.withRangeFilter(timestampAfterIdentifier, new RangeGreaterThanOrEqual(filter.after));
110-
}
111-
}
102+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter.before, filter.after);
112103

113104
if (filter.canCreate !== undefined) {
114105
elasticQuery = this.getRoleCondition(elasticQuery, 'ESDTRoleNFTCreate', address, filter.canCreate);
@@ -177,6 +168,38 @@ export class ElasticIndexerHelper {
177168
return query.withCondition(condition, QueryType.Nested('roles', [new MatchQuery(`roles.${name}`, targetAddress)]));
178169
}
179170

171+
private applyTimestampRangeFilter(query: ElasticQuery, before?: number, after?: number): ElasticQuery {
172+
if (before === undefined && after === undefined) {
173+
return query;
174+
}
175+
176+
const legacyMustQueries: AbstractQuery[] = [];
177+
const modernMustQueries: AbstractQuery[] = [QueryType.Exists('timestampMs')];
178+
179+
if (before !== undefined) {
180+
legacyMustQueries.push(QueryType.Range('timestamp', new RangeLowerThanOrEqual(this.toTimestampSeconds(before))));
181+
modernMustQueries.push(QueryType.Range('timestampMs', new RangeLowerThanOrEqual(this.toTimestampMilliseconds(before))));
182+
}
183+
184+
if (after !== undefined) {
185+
legacyMustQueries.push(QueryType.Range('timestamp', new RangeGreaterThanOrEqual(this.toTimestampSeconds(after))));
186+
modernMustQueries.push(QueryType.Range('timestampMs', new RangeGreaterThanOrEqual(this.toTimestampMilliseconds(after))));
187+
}
188+
189+
return query.withMustCondition(QueryType.Should([
190+
QueryType.Must(modernMustQueries),
191+
QueryType.Must(legacyMustQueries, [QueryType.Exists('timestampMs')]),
192+
]));
193+
}
194+
195+
private toTimestampSeconds(value: number): number {
196+
return TimeUtils.isTimestampInSeconds(value) ? value : Math.floor(value / 1000);
197+
}
198+
199+
private toTimestampMilliseconds(value: number): number {
200+
return TimeUtils.isTimestampInSeconds(value) ? value * 1000 : value;
201+
}
202+
180203
public buildElasticNftFilter(filter: NftFilter, identifier?: string, address?: string): ElasticQuery {
181204
let elasticQuery = ElasticQuery.create()
182205
.withCondition(QueryConditionOptions.must, QueryType.Exists('identifier'));
@@ -286,14 +309,7 @@ export class ElasticIndexerHelper {
286309
}
287310
}
288311

289-
if (filter.before) {
290-
const timestampBeforeIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
291-
elasticQuery = elasticQuery.withRangeFilter(timestampBeforeIdentifier, new RangeLowerThanOrEqual(filter.before));
292-
}
293-
if (filter.after) {
294-
const timestampAfterIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
295-
elasticQuery = elasticQuery.withRangeFilter(timestampAfterIdentifier, new RangeGreaterThanOrEqual(filter.after));
296-
}
312+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter.before, filter.after);
297313

298314
if (filter.nonceBefore) {
299315
elasticQuery = elasticQuery.withRangeFilter('nonce', new RangeLowerThanOrEqual(filter.nonceBefore));
@@ -421,14 +437,7 @@ export class ElasticIndexerHelper {
421437
elasticQuery = elasticQuery.withCondition(QueryConditionOptions.must, QueryType.Match('status', filter.status));
422438
}
423439

424-
if (filter.before) {
425-
const timestampBeforeIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
426-
elasticQuery = elasticQuery.withRangeFilter(timestampBeforeIdentifier, new RangeLowerThanOrEqual(filter.before));
427-
}
428-
if (filter.after) {
429-
const timestampAfterIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
430-
elasticQuery = elasticQuery.withRangeFilter(timestampAfterIdentifier, new RangeGreaterThanOrEqual(filter.after));
431-
}
440+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter.before, filter.after);
432441

433442
if (filter.senderOrReceiver) {
434443
elasticQuery = elasticQuery
@@ -572,14 +581,7 @@ export class ElasticIndexerHelper {
572581
.withMustMatchCondition('status', filter.status)
573582
.withMustMultiShouldCondition(filter.tokens, token => QueryType.Match('tokens', token, QueryOperator.AND));
574583

575-
if (filter.before) {
576-
const timestampBeforeIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
577-
elasticQuery = elasticQuery.withRangeFilter(timestampBeforeIdentifier, new RangeLowerThanOrEqual(filter.before));
578-
}
579-
if (filter.after) {
580-
const timestampAfterIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
581-
elasticQuery = elasticQuery.withRangeFilter(timestampAfterIdentifier, new RangeGreaterThanOrEqual(filter.after));
582-
}
584+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter.before, filter.after);
583585

584586
if (filter.functions && filter.functions.length > 0) {
585587
if (filter.functions.length === 1 && filter.functions[0] === '') {
@@ -684,14 +686,7 @@ export class ElasticIndexerHelper {
684686

685687
let elasticQuery = ElasticQuery.create().withCondition(QueryConditionOptions.must, mustQueries);
686688

687-
if (filter && filter.before) {
688-
const timestampBeforeIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
689-
elasticQuery = elasticQuery.withRangeFilter(timestampBeforeIdentifier, new RangeLowerThanOrEqual(filter.before));
690-
}
691-
if (filter && filter.after) {
692-
const timestampAfterIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
693-
elasticQuery = elasticQuery.withRangeFilter(timestampAfterIdentifier, new RangeGreaterThanOrEqual(filter.after));
694-
}
689+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter?.before, filter?.after);
695690

696691
if (filter && filter.identifiers) {
697692
elasticQuery = elasticQuery.withMustCondition(QueryType.Should(
@@ -794,15 +789,7 @@ export class ElasticIndexerHelper {
794789
buildApplicationFilter(filter: ApplicationFilter): ElasticQuery {
795790
let elasticQuery = ElasticQuery.create();
796791

797-
if (filter.after) {
798-
const timestampIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
799-
elasticQuery = elasticQuery.withRangeFilter(timestampIdentifier, new RangeGreaterThanOrEqual(filter.after));
800-
}
801-
802-
if (filter.before) {
803-
const timestampIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
804-
elasticQuery = elasticQuery.withRangeFilter(timestampIdentifier, new RangeLowerThanOrEqual(filter.before));
805-
}
792+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter.before, filter.after);
806793

807794
return elasticQuery;
808795
}
@@ -823,15 +810,7 @@ export class ElasticIndexerHelper {
823810
public buildEventsFilter(filter: EventsFilter): ElasticQuery {
824811
let elasticQuery = ElasticQuery.create();
825812

826-
if (filter.before) {
827-
const timestampIdentifier = TimeUtils.isTimestampInSeconds(filter.before) ? 'timestamp' : 'timestampMs';
828-
elasticQuery = elasticQuery.withRangeFilter(timestampIdentifier, new RangeLowerThanOrEqual(filter.before));
829-
}
830-
831-
if (filter.after) {
832-
const timestampIdentifier = TimeUtils.isTimestampInSeconds(filter.after) ? 'timestamp' : 'timestampMs';
833-
elasticQuery = elasticQuery.withRangeFilter(timestampIdentifier, new RangeGreaterThanOrEqual(filter.after));
834-
}
813+
elasticQuery = this.applyTimestampRangeFilter(elasticQuery, filter.before, filter.after);
835814

836815
if (filter.identifier) {
837816
elasticQuery = elasticQuery.withMustMatchCondition('identifier', filter.identifier);

src/common/indexer/elastic/elastic.indexer.service.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,11 +1048,26 @@ export class ElasticIndexerService implements IndexerInterface {
10481048
}
10491049

10501050
async getBlockByTimestampAndShardId(timestamp: number, shardId: number): Promise<Block | undefined> {
1051-
const timestampIdentifier = TimeUtils.isTimestampInSeconds(timestamp) ? 'timestamp' : 'timestampMs';
1051+
const timestampInSeconds = TimeUtils.isTimestampInSeconds(timestamp) ? timestamp : Math.floor(timestamp / 1000);
1052+
const timestampInMilliseconds = TimeUtils.isTimestampInSeconds(timestamp) ? timestamp * 1000 : timestamp;
1053+
1054+
const timestampQuery = QueryType.Should([
1055+
QueryType.Must([
1056+
QueryType.Exists('timestampMs'),
1057+
QueryType.Range('timestampMs', new RangeGreaterThanOrEqual(timestampInMilliseconds)),
1058+
]),
1059+
QueryType.Must([
1060+
QueryType.Range('timestamp', new RangeGreaterThanOrEqual(timestampInSeconds)),
1061+
], [QueryType.Exists('timestampMs')]),
1062+
]);
1063+
10521064
const elasticQuery = ElasticQuery.create()
1053-
.withRangeFilter(timestampIdentifier, new RangeGreaterThanOrEqual(timestamp))
1065+
.withMustCondition(timestampQuery)
10541066
.withCondition(QueryConditionOptions.must, [QueryType.Match('shardId', shardId, QueryOperator.AND)])
1055-
.withSort([{ name: 'timestamp', order: ElasticSortOrder.ascending }]);
1067+
.withSort([
1068+
{ name: 'timestamp', order: ElasticSortOrder.ascending },
1069+
{ name: 'timestampMs', order: ElasticSortOrder.ascending },
1070+
]);
10561071

10571072
const blocks: Block[] = await this.elasticService.getList('blocks', '_search', elasticQuery);
10581073

0 commit comments

Comments
 (0)