Dynogels: Query using OR comparison - javascript

I am trying to optimise the following scans into a single scan (or query). The only way I see is to use to use a OR comparator using DynamoDB. I am using dynogels (fork of vogels) in my application but sadly I am not aware of any OR query functionality in there.
let arrivals = yield Reservation.scan()
.where('room').equals(room)
.where('arrival').between(from, to)
.execAsync().then((reply) => reply.Items.map((item) => item.get()));
let departures = yield Reservation.scan()
.where('room').equals(room)
.where('departure').between(from, to)
.execAsync().then((reply) => reply.Items.map((item) => item.get()));
let combined = arrivals.concat(departures);
return Promise.resolve(combined);
Proposed optimisation:
return Reservation.scan()
.where('room').equals(room)
.where('arrival').between(from, to)
.or.where('departure').between(from, to)
.execAsync().then((reply) => reply.Items.map((item) => item.get()));
The scans get me the reservations that end (departure) or start (arrival) (or both) in a specified date range (from, to).

I think this can be achieved using filterexpression.
Sample code using filterexpression:-
const scanItem = Reservation.scan().filterExpression('room = :idVal AND ((arrival BETWEEN :arrDateVal1 AND :arrDateVal2) OR (departure BETWEEN :depDateVal1 AND :depDateVal2)) ')
.expressionAttributeValues({ ':idVal' : '2', ':arrDateVal1' : '21-APR-2017', ':arrDateVal2' : '23-APR-2017'
,':depDateVal1' : '21-APR-2017', ':depDateVal2' : '23-APR-2017'});
scanItem.exec((err, result) => {if(!err) {console.log(JSON.stringify(result,undefined, 2))}});
Note:-
Not sure whether you wanted to specifically use where rather than filterexpression (or) just wanted to achieve the result regardless of where or filterexpression.

Related

I'm trying to make an array with only values ​that are not contained in the other array (non-repeating)

I have an array of available users that can be invited and also another array with all joined users to the particular chat. I need to check which of the available users have joined the chat and should be listed elsewhere.
Finally, I want to get an array with only the available users who have not joined the chat.
let availablеUsers = [{id:1,name:'Dani'}, {id:2,name:'Ani'}, {id:3,name:'Marta'}]
let allUsers = [{id:2,name:'Ani'},{id:10,name:'John'}, {id:3,name:'Marta'}]
The first thing I try to do is find those who are already participating in the chat:
let joinedUsers = availablеUsers.map((user) => {
return allUsers?.find((u) => u.id === user.id);
});
And i get this : [undefined, {… Аni}, {… Marta}]
Then I try to filter the array of available users so that I remove from it those that are in the newly created array and here's the problem I don't know how to do this :/
My idea is something like that:
availablеUsers = availablеUsers.filter((user) => {
//HERE I don't know what logic to write
return joinedUsers?.map((m) => m?.id !== user.id); // this doesn't work, just an example
});
My goal is to have only those users not contained in the other remain in the availableUsers array.
In the example I have given at the end in the array should remain only {id:1,name:'Dani'}
I welcome any suggestions. If it can do it with chaining, without the extra variable for joinedUsers it would be even better!
There's no need for joinedUsers. Just use find() or some() in the filter() callback, and invert the test.
availableUsers = availableUsers.filter(user => !allUsers.some(u => u.id == user.id))
if users are uniquely identified by id you can use just a filter with a Set of known users:
let availablеUsers = [{id:1,name:'Dani'}, {id:2,name:'Ani'}, {id:3,name:'Marta'}]
let allUsers = [{id:2,name:'Ani'},{id:10,name:'John'}, {id:3,name:'Marta'}]
let joinedUsers = availablеUsers.filter(
function ({id}) {
return this.has(id);
},
new Set(allUsers.map(({id}) => id))
);
Accordingly, you can use the same to update availablеUsers in one go:
availablеUsers = availablеUsers.filter(
function ({id}) {
return !this.has(id);
},
new Set(allUsers.map(({id}) => id))
);
it's not super clear why or when you need !== vs === but the concept is: use a set and use filter instead of map when you want to filter + a Set works harder while constructed but it's blazing fast while used via has()

Assign values from one set of key/value pairs to keys of another?

I'm working with the outputs of an Intranet I don't control.
I have this string:
let template = 'LAWYER=|FIRM=|SUIT_DESCRIPTION=|DEF_COMMENT=|PLF_COMMENT=|';
It goes on longer, but that's the pattern.
Now there's another similar string, but with data assigned, as in this example:
let current= 'FIRM=Smith and Wesson LLP|SUIT_DESCRIPTION=It\'s a royal mess|PLF_COMMENT=some freeform text|LAWYER=Bob Smith';
Now, notice that not every element in template is necessarily represented in current, and the order may be different (if the latter fact is a big deal, I can ensure the order is the same).
What I'm trying to do, is take every element that is in current, and populate the matching element in template, if it exists. (or, alternatively and potentially preferred, insert every non-matching element in template into current, but ideally in the same order as template).
Using the date above, the result I'm looking for is:
result = 'LAWYER=Bob Smith|FIRM=Smith and Wesson LLP|SUIT_DESCRIPTION=It\'s a royal mess|DEF_COMMENT=|PLF_COMMENT=some freeform text|';
I'm not very accomplished with JavaScript :(
I tried various things in JSFiddle using split() and match() but I just made a mess of it.
// Convert the template to an array of keys
const getKeys = str => str.split('|').map(entry => entry.split('=')[0]);
// Convert the data to an object
const toObj = str => Object.fromEntries(str.split('|').map(entry => entry.split('=')));
// Reconcile the data with the template
const compile = (templateStr, dataStr) => {
const keys = getKeys(templateStr);
const data = toObj(dataStr);
return keys.reduce((results, key) => {
if(key) results.push([key, data[key] ?? '']);
return results;
}, []);
};
// Convert the results back into a string
const toString = data => data.map(entry => entry.join('=')).join('|') + '|';
// And then a test
let template = 'LAWYER=|FIRM=|SUIT_DESCRIPTION=|DEF_COMMENT=|PLF_COMMENT=|';
let current = 'FIRM=Smith and Wesson LLP|SUIT_DESCRIPTION=It\'s a royal mess|PLF_COMMENT=some freeform text|LAWYER=Bob Smith';
console.log(toString(compile(template, current)));

Split out props.location.search value

I'm trying to split out the values from props.location.search in React/Redux. I've successfully obtained the mixOne split however I can't seem to return the value of quantity. Here's my code:
const mixOne = props.location.search
? String(props.location.search.split("mixOne=")[1])
: "None";
const quantity = props.location.search
? Number(props.location.search.split("=")[1])
: 1;
And here's the URL that gets generated:
const addToCartHandler = () => {
props.history.push(
`/Cart/${productId}?quantity=${quantity}?mixOne=${mixOne}`
);
};
As you can see quantity returns null, when I need the value selected
props.location.search.split("=") on "?quantity=1?mixOne=Grape" would return [ '?quantity', '1?mixOne', 'Grape' ] since the next = is not until after mixOne.
There's a few different fixes here.
Your query string is invalid– a ? denotes the start of the query string. Separate parameters should be split up using & ampersand characters. It should look like this: ?quantity=1&mixOne=Grape
If you follow the standard here, you can then split it two ways: by = and then by & to get the different parameters. However, there is an easier way.
Using the new-ish URLSearchParams API, you can parse your parameters in a predictable way:
// Use the constructor with your `props.location.search`
const queryParams = new URLSearchParams(props.location.search);
// Use the getters to grab a specific value
const quantity = queryParams.get("quantity");
// Ensure it's a number for safety
const quantityNum = Number(quantity);
// ... the rest of your code here
The query is wrong. You're using double question marks. The second ? should be replaced with &.
?quantity=1&mixOne=Grape

Conditional statement within template literal concatenation?

I am making an API call like this:
posts: (ppp, page) =>
requests.get(`/wp-json/wp/v2/posts?per_page=${ppp}&page=${page}`)
I am not always going to be passing in posts per page or page though, so I would like to only concatenate those variables if they exist. I tried below but I can't seem to get the formatting down:
requests.get(`/wp-json/wp/v2/posts?`${ppp ? `'per_page='${ppp} : `''` `${page} ? `'&page=' ${page}` :''`)
Besides that your second solution contains syntax errors, it also isn't the most readable way to do that...
But why are you trying to reinvent the wheel?
You can use the URL API which is available both on the client-side and in Node.js:
posts: (ppp, page) => {
const url = new URL('/wp-json/wp/v2/posts')
if(ppp) url.searchParams.append('per_page', ppp)
if(page) url.searchParams.append('page', page)
return requests.get(url.href)
}
However, if you can't use the above solution for some reason, you can still implement a similar algorithm that works like the above solution. For example, you can use an array:
posts: (ppp, page) => {
const urlParams = []
if(ppp) urlParams.push(`per_page=${ppp}`)
if(page) urlParams.push(`page=${page}`)
return requests.get(`/wp-json/wp/v2/posts?${ urlParams.join('&') }`)
}
Or an even more flexible solution:
posts: (ppp, page) => {
const urlParams = {
per_page: ppp, //per_page=ppp
page, //page=page
//Add more here if you want
}
return requests.get(`/wp-json/wp/v2/posts?${
Object
.entries(urlParams)
.filter(([k, v]) => v) //If value is truthy
.map(e => e.join('=')) //Concatenate key and value with =
.join('&') //Concatenate key-value pairs with &
}`)
}
But, if you want to stick to you version, here's a fixed example of it:
requests.get(`/wp-json/wp/v2/posts?${ppp ? `per_page=${ppp}` : ''}${(ppp && page) ? '&' : ''}${page ? `page=${page}` : ''}`)

firebase -> date order reverse

I am currently making an app using Firebase.
It is one of those bulletin boards that can be seen anywhere on the web.
But there was one problem.
This is a matter of date sorting.
I want to look at the recent date first, but I always see only the data I created first.
postRef.orderByChild('createData').startAt(reverseDate).limitToFirst(1).on('child_added',(data)=>{
console.log(data.val().name + data.val().createData);
})
result - >hello1496941142093
My firebase tree
My code is the same as above.
How can I check my recent posts first?
How Do I order reverse of firebase database?
The Firebase Database will always return results in ascending order. There is no way to reverse them.
There are two common workaround for this:
Let the database do the filtering, but then reverse the results client-side.
Add an inverted value to the database, and use that for querying.
These options have been covered quite a few times before. So instead of repeating, I'll give a list of previous answers:
Display posts in descending posted order
Sort firebase data in descending order using negative timestamp
firebase sort reverse order
Is it possible to reverse a Firebase list?
many more from this list: https://www.google.com/search?q=site:stackoverflow.com+firebase+reverse%20sort%20javascript
You can simply make a function to reverse the object and then traversing it.
function reverseObject(object) {
var newObject = {};
var keys = [];
for (var key in object) {
keys.push(key);
}
for (var i = keys.length - 1; i >= 0; i--) {
var value = object[keys[i]];
newObject[keys[i]]= value;
}
return newObject;
}
This is how I solved it:
First I made a query in my service where I filter by date in milliseconds:
getImages (): Observable<Image[]> {
this.imageCollection = this.asf.collection<Image>('/images', ref => ref.orderBy('time').startAt(1528445969388).endAt(9999999999999));
this.images = this.imageCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Image;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
return this.images;
}
Then to get the newest date first I added this to my component where I call the method from my service:
let date = new Date;
let time = 9999999999999 - date.getTime();
console.log(time);
I pass the time let as the date. Since a newer date will be a bigger number to deduct from the 9999999999999, the newest date will turn up first in my query inside my service.
Hope this solved it for you
If you want to display it in the front end, I suggest that after you retrieve the data, use the reverse() function of JavaScript.
Example:
let result = postRef
.orderByChild("createData")
.startAt(reverseDate)
.limitToFirst(1)
.on("child_added", data => {
console.log(data.val().name + data.val().createData);
});
result.reverse();
Ive ended changing how I create my list on the frontend part.
was
posts.add(post);
changed to
posts.insert(0, post);
You could use a method where you save the same or alternate child with a negative value and then parse it.
postRef.orderByChild('createData').orderByChild('createData').on('child_added',(data)=>{
console.log(data.val().name + data.val().createData);})
Far more easier is just use Swift's reversed():
https://developer.apple.com/documentation/swift/array/1690025-reversed
https://developer.apple.com/documentation/swift/reversedcollection
let decodedIds = try DTDecoder().decode([String].self, from: value)
// we reverse it, because we want most recent orders at the top
let reversedDecodedIds = decodedIds.reversed().map {$0}
orderBy("timestamp", "desc")
I think you can give a second argument name "desc".
It worked for me

Categories