Skip to content

Commit f795693

Browse files
committed
sync with java: d3ec2c31bb8774b8cf3e07b3df4a759b277da483
1 parent fde8f97 commit f795693

File tree

3 files changed

+754
-1
lines changed

3 files changed

+754
-1
lines changed

.github/workflows/RavenClient.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424

2525
strategy:
2626
matrix:
27-
node-version: [10.x, 12.x, 14.x]
27+
node-version: [10.x, 12.x, 14.x, 16.x]
2828
serverVersion: ["5.1", "5.2"]
2929
fail-fast: false
3030

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
import { GetTermsOperation, IDocumentStore } from "../../../../src";
2+
import { disposeTestDocumentStore, testContext } from "../../../Utils/TestUtil";
3+
import { AbstractRawJavaScriptCountersIndexCreationTask } from "../../../../src/Documents/Indexes/Counters/AbstractRawJavaScriptCountersIndexCreationTask";
4+
import { Address, Company, User } from "../../../Assets/Entities";
5+
import { assertThat } from "../../../Utils/AssertExtensions";
6+
7+
describe("BasicCountersIndexes_JavaScript", function () {
8+
9+
let store: IDocumentStore;
10+
11+
beforeEach(async function () {
12+
store = await testContext.getDocumentStore();
13+
});
14+
15+
afterEach(async () =>
16+
await disposeTestDocumentStore(store));
17+
18+
it("basicMapIndex", async () => {
19+
{
20+
const session = store.openSession();
21+
const company = new Company();
22+
await session.store(company, "companies/1");
23+
session.countersFor(company).increment("heartRate", 7);
24+
25+
await session.saveChanges();
26+
}
27+
28+
const timeSeriesIndex = new MyCounterIndex();
29+
const indexDefinition = timeSeriesIndex.createIndexDefinition();
30+
31+
await timeSeriesIndex.execute(store);
32+
33+
await testContext.waitForIndexing(store);
34+
35+
let terms = await store.maintenance.send(new GetTermsOperation("MyCounterIndex", "heartBeat", null));
36+
assertThat(terms)
37+
.hasSize(1);
38+
assertThat(terms)
39+
.contains("7");
40+
41+
terms = await store.maintenance.send(new GetTermsOperation("MyCounterIndex", "user", null));
42+
assertThat(terms)
43+
.hasSize(1)
44+
.contains("companies/1");
45+
46+
terms = await store.maintenance.send(new GetTermsOperation("MyCounterIndex", "name", null));
47+
assertThat(terms)
48+
.hasSize(1)
49+
.contains("heartrate");
50+
51+
{
52+
const session = store.openSession();
53+
const company1 = await session.load("companies/1", Company);
54+
session.countersFor(company1)
55+
.increment("heartRate", 3);
56+
57+
const company2 = new Company();
58+
await session.store(company2, "companies/2");
59+
session.countersFor(company2)
60+
.increment("heartRate", 4);
61+
62+
const company3 = new Company();
63+
await session.store(company3, "companies/3");
64+
session.countersFor(company3)
65+
.increment("heartRate", 6);
66+
67+
const company999 = new Company();
68+
await session.store(company999, "companies/999");
69+
session.countersFor(company999)
70+
.increment("heartRate_Different", 999);
71+
72+
await session.saveChanges();
73+
}
74+
75+
await testContext.waitForIndexing(store);
76+
77+
terms = await store.maintenance.send(new GetTermsOperation("MyCounterIndex", "heartBeat", null));
78+
assertThat(terms)
79+
.hasSize(3)
80+
.contains("10")
81+
.contains("4")
82+
.contains("6");
83+
84+
terms = await store.maintenance.send(new GetTermsOperation("MyCounterIndex", "user", null));
85+
assertThat(terms)
86+
.hasSize(3)
87+
.contains("companies/1")
88+
.contains("companies/2")
89+
.contains("companies/3");
90+
91+
terms = await store.maintenance.send(new GetTermsOperation("MyCounterIndex", "name", null));
92+
assertThat(terms)
93+
.hasSize(1)
94+
.contains("heartrate");
95+
96+
// skipped rest of the test
97+
});
98+
99+
it("basicMapReduceIndexWithLoad", async function () {
100+
{
101+
const session = store.openSession();
102+
for (let i = 0; i < 10; i++) {
103+
const address = new Address();
104+
address.city = "NY";
105+
await session.store(address, "addresses/" + i);
106+
107+
const user = new User();
108+
user.addressId = address.id;
109+
await session.store(user, "users/" + i);
110+
111+
session.countersFor(user)
112+
.increment("heartRate", 180 + i);
113+
}
114+
115+
await session.saveChanges();
116+
}
117+
118+
const timeSeriesIndex = new AverageHeartRate_WithLoad();
119+
const indexName = timeSeriesIndex.getIndexName();
120+
const indexDefinition = timeSeriesIndex.createIndexDefinition();
121+
122+
await timeSeriesIndex.execute(store);
123+
124+
await testContext.waitForIndexing(store);
125+
126+
let terms = await store.maintenance.send(new GetTermsOperation(indexName, "heartBeat", null));
127+
assertThat(terms)
128+
.hasSize(1)
129+
.contains("184.5");
130+
131+
terms = await store.maintenance.send(new GetTermsOperation(indexName, "count", null));
132+
assertThat(terms)
133+
.hasSize(1)
134+
.contains("10");
135+
136+
terms = await store.maintenance.send(new GetTermsOperation(indexName, "city", null));
137+
assertThat(terms)
138+
.hasSize(1)
139+
.contains("ny");
140+
});
141+
142+
it("canMapAllCountersFromCollection", async function () {
143+
{
144+
const session = store.openSession();
145+
const company = new Company();
146+
await session.store(company, "companies/1");
147+
148+
session.countersFor(company)
149+
.increment("heartRate", 7);
150+
session.countersFor(company)
151+
.increment("likes", 3);
152+
153+
await session.saveChanges();
154+
}
155+
156+
const timeSeriesIndex = new MyCounterIndex_AllCounters();
157+
const indexName = timeSeriesIndex.getIndexName();
158+
const indexDefinition = timeSeriesIndex.createIndexDefinition();
159+
160+
await timeSeriesIndex.execute(store);
161+
162+
await testContext.waitForIndexing(store);
163+
164+
let terms = await store.maintenance.send(new GetTermsOperation(indexName, "heartBeat", null));
165+
assertThat(terms)
166+
.hasSize(2)
167+
.contains("7")
168+
.contains("3");
169+
170+
terms = await store.maintenance.send(new GetTermsOperation(indexName, "user", null));
171+
assertThat(terms)
172+
.hasSize(1)
173+
.contains("companies/1");
174+
175+
terms = await store.maintenance.send(new GetTermsOperation(indexName, "name", null));
176+
assertThat(terms)
177+
.hasSize(2)
178+
.contains("heartrate")
179+
.contains("likes");
180+
});
181+
182+
it("basicMultiMapIndex", async function () {
183+
const timeSeriesIndex = new MyMultiMapCounterIndex();
184+
185+
await timeSeriesIndex.execute(store);
186+
187+
{
188+
const session = store.openSession();
189+
const company = new Company();
190+
await session.store(company);
191+
192+
session.countersFor(company)
193+
.increment("heartRate", 3);
194+
session.countersFor(company)
195+
.increment("heartRate2", 5);
196+
197+
const user = new User();
198+
await session.store(user);
199+
session.countersFor(user)
200+
.increment("heartRate", 2);
201+
202+
await session.saveChanges();
203+
}
204+
205+
await testContext.waitForIndexing(store);
206+
207+
{
208+
const session = store.openSession();
209+
const results = await session.query(MyMultiMapCounterIndexResult, MyMultiMapCounterIndex)
210+
.all();
211+
212+
assertThat(results)
213+
.hasSize(3);
214+
}
215+
});
216+
217+
it("counterNamesFor", async function () {
218+
const index = new Companies_ByCounterNames();
219+
await index.execute(store);
220+
221+
{
222+
const session = store.openSession();
223+
const company = new Company();
224+
await session.store(company, "companies/1");
225+
226+
await session.saveChanges();
227+
}
228+
229+
await testContext.waitForIndexing(store);
230+
231+
let terms = await store.maintenance.send(new GetTermsOperation(index.getIndexName(), "name", null));
232+
assertThat(terms)
233+
.hasSize(0);
234+
235+
terms = await store.maintenance.send(new GetTermsOperation(index.getIndexName(), "names_IsArray", null));
236+
assertThat(terms)
237+
.hasSize(1)
238+
.contains("true");
239+
240+
{
241+
const session = store.openSession();
242+
const company = await session.load("companies/1", Company);
243+
244+
session.countersFor(company)
245+
.increment("heartRate", 3);
246+
session.countersFor(company)
247+
.increment("heartRate2", 7);
248+
249+
await session.saveChanges();
250+
}
251+
252+
await testContext.waitForIndexing(store);
253+
254+
terms = await store.maintenance.send(new GetTermsOperation(index.getIndexName(), "names", null));
255+
assertThat(terms)
256+
.hasSize(2)
257+
.contains("heartrate")
258+
.contains("heartrate2");
259+
260+
terms = await store.maintenance.send(new GetTermsOperation(index.getIndexName(), "names_IsArray", null));
261+
assertThat(terms)
262+
.hasSize(1)
263+
.contains("true");
264+
});
265+
});
266+
267+
class MyCounterIndex extends AbstractRawJavaScriptCountersIndexCreationTask {
268+
public constructor() {
269+
super();
270+
271+
this.maps.add(
272+
"counters.map('Companies', 'HeartRate', function (counter) {\n" +
273+
"return {\n" +
274+
" heartBeat: counter.Value,\n" +
275+
" name: counter.Name,\n" +
276+
" user: counter.DocumentId\n" +
277+
"};\n" +
278+
"})"
279+
);
280+
}
281+
}
282+
283+
284+
class AverageHeartRate_WithLoad extends AbstractRawJavaScriptCountersIndexCreationTask {
285+
286+
constructor() {
287+
super();
288+
289+
this.maps.add("counters.map('Users', 'heartRate', function (counter) {\n" +
290+
"var user = load(counter.DocumentId, 'Users');\n" +
291+
"var address = load(user.addressId, 'Addresses');\n" +
292+
"return {\n" +
293+
" heartBeat: counter.Value,\n" +
294+
" count: 1,\n" +
295+
" city: address.city\n" +
296+
"};\n" +
297+
"})");
298+
299+
this.reduce = "groupBy(r => ({ city: r.city }))\n" +
300+
" .aggregate(g => ({\n" +
301+
" heartBeat: g.values.reduce((total, val) => val.heartBeat + total, 0) / g.values.reduce((total, val) => val.count + total, 0),\n" +
302+
" city: g.key.city,\n" +
303+
" count: g.values.reduce((total, val) => val.count + total, 0)\n" +
304+
" }))";
305+
}
306+
}
307+
308+
class AverageHeartRate_WithLoadResult {
309+
public heartBeat: number;
310+
public city: string;
311+
public count: number;
312+
}
313+
314+
class MyCounterIndex_AllCounters extends AbstractRawJavaScriptCountersIndexCreationTask {
315+
public constructor() {
316+
super();
317+
318+
this.maps.add("counters.map('Companies', function (counter) {\n" +
319+
"return {\n" +
320+
" heartBeat: counter.Value,\n" +
321+
" name: counter.Name,\n" +
322+
" user: counter.DocumentId\n" +
323+
"};\n" +
324+
"})");
325+
}
326+
}
327+
328+
class MyMultiMapCounterIndex extends AbstractRawJavaScriptCountersIndexCreationTask {
329+
public constructor() {
330+
super();
331+
332+
this.maps.add("counters.map('Companies', 'heartRate', function (counter) {\n" +
333+
"return {\n" +
334+
" heartBeat: counter.Value,\n" +
335+
" name: counter.Name,\n" +
336+
" user: counter.DocumentId\n" +
337+
"};\n" +
338+
"})");
339+
340+
this.maps.add("counters.map('Companies', 'heartRate2', function (counter) {\n" +
341+
"return {\n" +
342+
" heartBeat: counter.Value,\n" +
343+
" name: counter.Name,\n" +
344+
" user: counter.DocumentId\n" +
345+
"};\n" +
346+
"})");
347+
348+
this.maps.add("counters.map('Users', 'heartRate', function (counter) {\n" +
349+
"return {\n" +
350+
" heartBeat: counter.Value,\n" +
351+
" name: counter.Name,\n" +
352+
" user: counter.DocumentId\n" +
353+
"};\n" +
354+
"})");
355+
}
356+
}
357+
358+
class MyMultiMapCounterIndexResult {
359+
public heartBeat: number;
360+
public name: string;
361+
public user: string;
362+
}
363+
364+
class Companies_ByCounterNames extends AbstractRawJavaScriptCountersIndexCreationTask {
365+
public constructor() {
366+
super();
367+
368+
this.maps.add("map('Companies', function (company) {\n" +
369+
"return ({\n" +
370+
" names: counterNamesFor(company)\n" +
371+
"})\n" +
372+
"})");
373+
}
374+
}

0 commit comments

Comments
 (0)