import { DataPage, FilterParams, PagingParams } from "pip-services3-commons-nodex"; import { IdentifiableMongoDbPersistence } from "pip-services3-mongodb-nodex"; import { FireMapTileBlockV1 } from "../data/version1/FireMapTileBlockV1"; import { IFireMapPersistence } from "./IFireMapPersistence"; export class FireMapMongoDbPersistence extends IdentifiableMongoDbPersistence implements IFireMapPersistence { public constructor() { super('firemap'); this._maxPageSize = 1000; } private composeFilter(filter: FilterParams): any { filter = filter || new FilterParams(); let criteria = []; let flng = filter.getAsNullableFloat('flng'); let flat = filter.getAsNullableFloat('flat'); let tlng = filter.getAsNullableFloat('tlng'); let tlat = filter.getAsNullableFloat('tlat'); let zoom = filter.getAsNullableInteger('zoom'); let coordinates = filter.getAsObject('coordinates'); if (typeof coordinates === "string") { coordinates = coordinates.split(','); } else { coordinates = null; } let flng2: number = null; let tlng2: number = null; // round to the next tile for current zoom if ([flng, flat, tlng, tlat].every(e => e != null)) { // if coordinates is left top and right bottom corners if (flat > tlat) [flat, tlat] = [tlat, flat]; // if coordinates pass through the last meridian if (flng > tlng) { flng2 = -180; tlng2 = tlng; tlng = 180; } } // get blocks for coordinates if (coordinates != null) { for (let location of coordinates) { let [lat, long] = location.split(';'); lat = parseFloat(lat); long = parseFloat(long); criteria = criteria.concat(...[ { $and: [ { flng: { $lte: long } }, { tlng: { $gte: long } }, { flat: { $gte: lat } }, { tlat: { $lte: lat } }, ]} ]); } criteria = [{$or: criteria}]; } if (flng != null && tlng != null && flat != null && tlat != null) { // check intersections of tile block and passed coordinates criteria = criteria.concat(...[ { $or: [ { $and: [{ flng: { $gte: flng } }, { flng: { $lte: tlng } }, { tlng: { $gte: tlng } }] }, { flng: { $lte: flng }, tlng: { $gte: tlng } }, { flng: { $gte: flng }, tlng: { $lte: tlng } }, ] } ]); criteria = criteria.concat(...[ { $or: [ { $and: [{ flat: { $lte: flat } }, { flat: { $gte: tlat } }, { tlat: { $lte: tlat } }] }, { flat: { $gte: flat }, tlat: { $lte: tlat } }, { flat: { $lte: flat }, tlat: { $gte: tlat } }, ] } ]); if (flng2 && tlng2) { criteria = criteria.concat(...[ { $or: [ { $and: [{ flng: { $gte: flng2 } }, { flng: { $lte: tlng2 } }, { tlng: { $gte: tlng2 } }] }, { flng: { $lte: flng2 }, tlng: { $gte: tlng2 } }, { flng: { $gte: flng2 }, tlng: { $lte: tlng2 } }, ] } ]); } } if (zoom != null) { criteria.push({ zoom: zoom }); } return criteria.length > 0 ? { $and: criteria } : null; } public async getTileBlocksByFilter(correlationId: string, filter: FilterParams, paging: PagingParams): Promise> { // get blocks in passed coordinates let page = await this.getPageByFilter(correlationId, this.composeFilter(filter), paging, null, null); return page; } public async updateTileBlocks(correlationId: string, updates: FireMapTileBlockV1[]): Promise { if (updates == null) { return; } let operations = []; for (let update of updates) { let updateItem = this.convertFromPublic(Object.assign({}, update)); operations.push({ updateOne: { filter: { _id: updateItem._id }, update: { $set: updateItem }, upsert: true, } }); } let result = await this._collection.bulkWrite(operations); if (result.writeErrors == null && result.writeConcernErrors == null) { this._logger.trace(correlationId, "Updated %s firemap blocks %s", this._collectionName, operations.length); } } }