RethinkDB, add derived columns on result - rethinkdb

I can seem to do this via map+merge
map( function(row) {
return row.merge( { newCol: 'ABC' } );
});
Problem is if I want to do a lookup from a static map e.g.
var LOOKUP_MAP = {key1: {text: 'Key 1'}};
Then below doesn't work
map( function(row) {
return row.merge({ newCol: LOOKUP_MAP[row('key')].text });
});
row('key'); seems to be lazily evaluated. Any idea how to do this?

You can use sth like this:
var LOOKUP_MAP = {key1: {text: 'Key 1'}};
r.db('salaries').table('salaries')
.map( function(row) {
return row.merge({ newCol: r.expr(LOOKUP_MAP)(row('key'))('text') });
});

Related

rxjs: subscribing to observable in map

My first observable returns an array of Persons. I want to update each person of that array with a list of clients from second observable. How do I do that? So far I have this:
const json: Person[] = [new Person('Alice'), new Person('Bob')];
const resultsObservable = new Observable<string[]>(subscriber => {
setTimeout(() => {
subscriber.next(['Client1', 'Client2', 'Client3']);
subscriber.complete();
}, 1000);
});
of(json).pipe(
switchMap( dataArray => {
return from(dataArray);
}),
map((x: Person) => {
resultsObservable.subscribe(r => {
x.clients = r;
});
return x;
}),
).subscribe(value => {
console.log(value);
});
}
Person:
export class Person{
name: string;
clients?: string[];
constructor(name: string) {
this.name = name;
}
}
But the problem is that return happens before the values are set, so at the end value of person.clients is undefined. How do I fix this? Or what is a better way to achieve what I'm trying to do?
Ok I think I found what I was looking for:
const result = persons.pipe(
mergeMap(p => resultsObservable.pipe(map(clients => {
p.clients = clients;
return p;
}))),
);
result.subscribe(p => console.log(p));

How to use #pnp/sp to query a person column in an SP list to get the name

I have a web part that which needs to retrieve the Name property of a person column (a people picker) so I can populate state with it and subsequently populate a field. Here's the function that queries the item:
private _jeChange = (ev: React.FormEvent<HTMLDivElement>, option?: IDropdownOption, index?: number) => {
this.setState({
SelectedJE: option.text,
}, () => {
const selJE = this.state.SelectedJE;
if (selJE && selJE.length > 0) {
let _item = this.state.MyListItems.find((item) => {
return item.JobRef == selJE;
});
this.setState({
JEDeptContact: _item.DeptContactId,
}, () => {
sp.web.lists.getByTitle("MyList").items.getById(_item.Id).select("DeptContact", "Lookup/Name", "Lookup/ID").expand("Lookup").get().then((item: any[]) => {
console.log(item);
});
});
}
});
}
The _item.DeptContactId successfully populates the state with the Id of the user in the person column, but I want the Name not the Id, how would I resolve the Id to the Name? Do I need to use expand to get the Name? If so how?
I've read this but I don't know where to use the expand:
https://pnp.github.io/pnpjs/sp/items/
Found it:
if(_item.DeptContactId){
sp.web.getUserById(_item.DeptContactId).select("Title", "DeptContact/Title").expand("DeptContact").get().then(r => {
this.setState({
JEDeptContact: r.Title,
});
});

Combining observable outputs in to one array

I need to make two calls to Firebase (as it doesn't support OR queries) and merge the output into one array at the end to return to the calling service.
I have something that gets pretty close but it outputs a 2D array of arrays (one for each call to Firebase). I've tried a few things and this is the best I can get to. Any help on tidying up the below would be great.
getAllFriends(): Observable<[Friendship[], Friendship[]]> {
const invitesSent = from(this.afAuth.currentUser.then(user => {
return user.uid;
}))
.pipe(
switchMap(
userid => {
return this.db.collection('friendships', ref => ref.where('inviter', '==', userid)).snapshotChanges().pipe(map(actions => {
return actions.map(action => {
const data = new Friendship(action.payload.doc.data());
data.id = action.payload.doc.id;
console.log(data);
return data;
});
}));
}
)
);
const invitesReceived = from(this.afAuth.currentUser.then(user => {
return user.uid;
}))
.pipe(
switchMap(
userid => {
return this.db.collection('friendships', ref => ref.where('invitee', '==', userid)).snapshotChanges().pipe(map(actions => {
return actions.map(action => {
const data = new Friendship(action.payload.doc.data());
data.id = action.payload.doc.id;
console.log(data);
return data;
});
}));
}
)
);
return combineLatest([invitesSent, invitesReceived]);
}
Friendship is just an object with property: value pairs, nothing special.
I have tried then putting a .pipe() after this returned observable but that just stops the subscription firing in the calling service.
What about returning, at the end, something like this
return combineLatest([invitesSent, invitesReceived]).pipe(
map(([frienships_1, friendships_2]) => ([...friedships_1, ...friendships_2]))
)

How to match partial nest properties passed to toHaveBeenCalledWith?

describe("Test", function() {
it("should pass", function() {
const callback = (data) => {};
const callBackSpy = jasmine.createSpy().and.callFake(callback);
const createData = (message) => {
return {
outerProp: "outerValue",
nestedObj: {
message: message,
prop1: "value1",
prop2: "value2"
}
};
};
const someApiCall = (callback) => {
setTimeout(callback(createData("test1")), 1000);
setTimeout(callback(createData("test2")), 2000);
setTimeout(callback(createData("hello world")), 5000);
};
someApiCall(callBackSpy);
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
nestedObj: {
prop1: "hello world"
}
})
);
});
});
I created a spy on a callback function which gets called multiple times with different parameters each time. The parameter is a complex nested object. I am looking for an object with a specific property.
If I specify all the properties like below, it works
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
outerProp: "outerValue",
nestedObj: {
message: "hello world",
prop1: "value1",
prop2: "value2"
}
})
);
But I don't know full properties. So, I am looking only for a specific property like below
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
nestedObj: {
message: "hello world"
}
})
);
Is there a way to make this work with a partial match?
You could try this.
expect(callBackSpy).toHaveBeenCalledWith(
jasmine.objectContaining({
nestedObj: jasmine.objectContaining({message: 'hello world'})
})
);
Another way would be to extract the arguments from the method call and test for specific nested attribute.
const arguments = callBackSpy.calls.argsFor(0);
expect(arguments[0]['nesedObject']['message'].toBe('hello world');

Is there a way to user pairs for Rxjs5?

Can not find Rx.Observable.pairs in Rxjs5,
what I need just convert an object into Observable and inspect the change for each property.
any ideas?
var a = { aa: "aa", bb: "bb" };
function pairs(obj) {
// List of object's key-value pairs
var keyValuePairs = Object.keys(obj).map(key => ({ key, value: obj[key] }));
// Convert to an Observable and return
return Rx.Observable.from(keyValuePairs);
}
var xxx = pairs(a);
xxx.subscribe(x => {
console.log(x);
})
a.aa = "mm";
You can accomplish this from scratch:
function pairs(obj) {
// List of object's key-value pairs
var keyValuePairs = Object.keys(obj).map(key => ({ key, value: obj[key]}));
// Convert to an Observable and return
return Rx.Observable.from(keyValuePairs);
}

Resources