diff --git a/src/core/Perspective.ts b/src/core/Perspective.ts index f7d616ce1..cb6f46ad9 100644 --- a/src/core/Perspective.ts +++ b/src/core/Perspective.ts @@ -222,6 +222,34 @@ export default class Perspective { // console.debug("getLinks 2") + const reverse = query.fromDate! >= query.untilDate!; + + function fromDateFilter(link: LinkExpression) { + if (reverse) { + return new Date(link.timestamp) <= query.fromDate! + } else { + return new Date(link.timestamp) >= query.fromDate! + } + } + + function untilDateFilter(link: LinkExpression) { + if (reverse) { + return new Date(link.timestamp) >= query.untilDate! + } else { + return new Date(link.timestamp) <= query.untilDate! + } + } + + function limitFilter(results: LinkExpression[]) { + if (query.limit) { + const startLimit = reverse ? results.length - query.limit : 0; + const endLimit = reverse ? (results.length - query.limit) + query.limit : query.limit; + return results.slice(startLimit, endLimit) + } + + return results; + } + if(query.source) { // console.debug("query.source", query.source) //@ts-ignore @@ -231,11 +259,11 @@ export default class Perspective { // @ts-ignore if(query.predicate) result = result.filter(l => l.data.predicate === query.predicate) //@ts-ignore - if (query.fromDate) result = result.filter(l => new Date(l.timestamp) >= query.fromDate!) - //@ts-ignore - if (query.untilDate) result = result.filter(l => new Date(l.timestamp) <= query.untilDate!) + if (query.fromDate) result = result.filter(fromDateFilter) + // @ts-ignore + if (query.untilDate) result = result.filter(untilDateFilter) // console.debug("result", result) - if (query.limit) result = result.slice(0, query.limit); + result = limitFilter(result); return result } @@ -247,10 +275,10 @@ export default class Perspective { // @ts-ignore if(query.predicate) result = result.filter(l => l.data.predicate === query.predicate) //@ts-ignore - if (query.fromDate) result = result.filter(l => new Date(l.timestamp) >= query.fromDate!) + if (query.fromDate) result = result.filter(fromDateFilter) //@ts-ignore - if (query.untilDate) result = result.filter(l => new Date(l.timestamp) <= query.untilDate!) - if (query.limit) result = result.slice(0, query.limit); + if (query.untilDate) result = result.filter(untilDateFilter) + result = limitFilter(result); return result } @@ -272,8 +300,21 @@ export default class Perspective { const mergedLinks: {[key: number]: LinkExpression} = {}; localLinks.forEach(l => mergedLinks[hashLinkExpression(l)] = l) remoteLinks.forEach(l => mergedLinks[hashLinkExpression(l)] = l) + + const reverse = query.fromDate! >= query.untilDate!; + + let values = Object.values(mergedLinks).sort((a, b) => { + return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(); + }); + + + if (query.limit) { + const startLimit = reverse ? values.length - query.limit : 0; + const endLimit = reverse ? (values.length - query.limit) + query.limit : query.limit; + values = values.slice(startLimit, endLimit) + } - return Object.values(mergedLinks) + return values; } async createPrologFacts(): Promise { diff --git a/src/tests/perspective.ts b/src/tests/perspective.ts index bd6ba7b93..c19cb48bd 100644 --- a/src/tests/perspective.ts +++ b/src/tests/perspective.ts @@ -42,9 +42,29 @@ export default function perspectiveTests(testContext: TestContext) { let addLink = await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target", predicate: "lang://predicate"})); let addLink2 = await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target2", predicate: "lang://predicate"})); - await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target3", predicate: "lang://predicate"})); - await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target4", predicate: "lang://predicate"})); - await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target5", predicate: "lang://predicate"})); + let addLink3 = await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target3", predicate: "lang://predicate"})); + let addLink4 = await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target4", predicate: "lang://predicate"})); + let addLink5 = await ad4mClient!.perspective.addLink(create.uuid, new Link({source: "lang://test", target: "lang://test-target5", predicate: "lang://predicate"})); + + // Get all the links + let queryLinksAll = await ad4mClient!.perspective.queryLinks(create.uuid, new LinkQuery({source: "lang://test", fromDate: new Date(new Date(addLink.timestamp).getTime()), untilDate: new Date()})); + expect(queryLinksAll.length).toEqual(5); + + + // Get all the links in ascending order + let queryLinksAsc = await ad4mClient!.perspective.queryLinks(create.uuid, new LinkQuery({source: "lang://test", fromDate: new Date(), untilDate: new Date("August 19, 1975 23:15:30"), limit: 3})); + expect(queryLinksAsc.length).toEqual(3); + expect(queryLinksAsc[0].data.target).toBe(addLink3.data.target) + expect(queryLinksAsc[1].data.target).toBe(addLink4.data.target) + expect(queryLinksAsc[2].data.target).toBe(addLink5.data.target) + + // Get all the links in ascending order + let queryLinksDesc = await ad4mClient!.perspective.queryLinks(create.uuid, new LinkQuery({source: "lang://test", fromDate: new Date("August 19, 1975 23:15:30"), untilDate: new Date(), limit: 3})); + expect(queryLinksDesc.length).toEqual(3); + expect(queryLinksDesc[0].data.target).toBe(addLink.data.target) + expect(queryLinksDesc[1].data.target).toBe(addLink2.data.target) + expect(queryLinksDesc[2].data.target).toBe(addLink3.data.target) + //Test can get all links but first by querying from second timestamp let queryLinks = await ad4mClient!.perspective.queryLinks(create.uuid, new LinkQuery({source: "lang://test", fromDate: new Date(new Date(addLink2.timestamp).getTime() - 1), untilDate: new Date()})); @@ -141,6 +161,7 @@ export default function perspectiveTests(testContext: TestContext) { expect(pSeenInUpdateCB.name).toStrictEqual(p1.name) const linkAdded = jest.fn() + // TODO: @fayeed update this await ad4mClient.perspective.addPerspectiveLinkAddedListener(p1.uuid, [linkAdded]) const linkRemoved = jest.fn() await ad4mClient.perspective.addPerspectiveLinkRemovedListener(p1.uuid, [linkRemoved])