add ascending or descending to url in React - javascript

I am trying to create a url based on the data I get from the user.if we consider this to be my url:
let url = new URL('http://localhost:8080/api/movies/search/search');
I add the search fields like this:
for (let item in data) {
url.searchParams.set(item,data[item]);
}
but at the end of my url I want to add the sort type for it to look something like this:
const url = `http://localhost:8080/api/movies/search/search?title=something&minRate=10&genre=action&sort=title,asc`;
so how should I add the last part with the comma:
,asc
to the url?

Based on comments on the question above...
If data is this:
{
title: 'the',
minRate: 2,
genre: 'action',
sortType: 'title',
type: 'asc'
}
And the result you want is this:
http://localhost:8080/api/movies/search/search?title=the&minRate=2&genre=action&sort=title,asc
Then data doesn't match what you're looking for. It has two properties called sortType and type, and you want one combined property called sort.
Project the object into the shape you want, then use that new object to build your params:
let data = {
title: 'the',
minRate: 2,
genre: 'action',
sortType: 'title',
type: 'asc'
};
let url = new URL('http://localhost:8080/api/movies/search/search');
// create the object you want:
let urlData = {
title: data.title,
minRate: data.minRate,
genre: data.genre,
sort: `${data.sortType},${data.type}`
};
// then add params from *that* object:
for (let item in urlData) {
url.searchParams.set(item, urlData[item]);
}
console.log(url);
(Note that the , character is URL-encoded by default.)
Basically, don't change the logic to work around the data structure. Keep the logic simple and change the data structure to what you need it to be.

Related

Filter inside the fetch with mongoDB query operators

how are you? I'm trying to move a filter inside the fetch I'm doing to bring my data from Builder.io and I'm struggling with one of them here. The title search works fine, but the second one don't. My objective is to filter between the entries to catch only the ones that match at least one of the annotationArray items.
The annotationArray can be, for example:
const annotationArray = ['Video', 'Image', 'GPS']
or just
const annotationArray = ['Video']
or whatever.
And the entries have an annotation field that consists in a string where I pass the annotations, like this:
const entries = [{title: 'First', annotation: 'Video, GPS'}, {title: 'Second', annotation: 'GPS'}, {title: 'Third', annotation: 'Video, Image'}]
So, for example, if the annotationArray is ['Video', 'GPS'], I want to fetch all of them. But if it's ['Video'], only the third and first, and so.
Currently I have this code
const sets = await builder.getAll('open-dataset', {
options: { noTargeting: true },
omit: 'data.blocks',
limit: 100,
query: {
data: {
title: { $regex: search, $options: 'i' },
annotation: { $regex: annotationArray && annotationArray.join(' '), $options: 'i' },
}
}
});
The result of annotationArray.join(' ') can be, for example, Video Image GPS or just Image. And annotation Video Image or whatever.
So I need to filter between the entries and fetch only the ones that contain at least one of the annotationArray strings.
My code is failing because currently it only fetches the ones that have all the annotationArray items, and not the ones that have at least one. I don't know how to do it with MondoDB query operators... previously, I had this code with javascript and it worked fine.
const filtered = entries.filter(item => annotationArray.some(data => item.annotation.includes(data)));
can somebody help me? thanks

Finding results that are part of a set with FlexSearch

I have an app that uses FlexSearch. In this app, I have an array of items that looks like this:
let results = [
{ id:'a', name:'The title', status:'in-stock' },
{ id:'b', name:'Another title', status:'out-of-stock' },
{ id:'c', name:'Some other', status:'discontinued' },
];
const resultSchema = {
id: 'id',
field: [
'name',
'status'
]
};
const resultIndex = new FlexSearch({
profile:'score',
doc: resultSchema
});
resultIndex.add(results);
My page has checkboxes for the statuses (in-stock, out-of-stock, and discontinued). My question is, how do I find results that are either a) in-stock or b) out-of-stock. I do not see a way to perform logical ORs with the where function. For example, I'd like to be able to say, give me all results that are either in-stock or out-of-stock. From a logical perspective, one could say, give me everything that is NOT discontinued. However, this is not my entire data set. For that reason, I'm trying to figure out how to do ORs within Flexsearch.
Thank you!
See the section Logical Operators in the readme. This seems to work:
const res = resultIndex.search([
{ field: 'status', query: 'in-stock', bool: 'or' },
{ field: 'status', query: 'out-of-stock', bool: 'or' },
]);
Strangely, { field: 'status', query: 'discontinued', bool: 'not' } didn't work when I tried it.
Doesn't using a custom function solve your problem?(found it in the document)
Something like this:
resultIndex.where(function(item){
return item.status === "in-stock" || item.status === "out-of-stock";
});

SequelizeJS - How to Map Nested (eager loading) Models for Raw Queries?

Below is an example of a raw query.
const query = `SELECT
links.name, links.type, links.code, links.originalUrl,
domains.id as 'domain.id', domains.host as 'domain.host',
count(
CASE WHEN hits.datetime > "${past}" AND hits.datetime <= "${now}" = true then 1 END
) as hitCount
FROM links
LEFT JOIN hits ON links.id = hits.linkId
LEFT JOIN domains ON links.domainId = domains.id
WHERE links.userId = ${req.user.id}
GROUP BY links.id, hits.linkId
ORDER BY hitCount DESC
LIMIT 5`;
const links = await sequelize.query(query.trim(), {
type: sequelize.QueryTypes.SELECT,
model: Link,
mapToModel: true
});
I am mapping the query result into the model Link with mapToModel: true. It works well but when I try to get some data from a joined table and map that into an object in model it doesn't convert into array.
For example I am trying to get domains like domains.id as 'domain.id', domains.host as 'domain.host', This is how I saw sequlize does the query for eager loaded data.
But when I get the result object the I don't get a nested domain object property.
// desired link object
{
id: 3,
name: 'My test link',
domain: {
id: 23,
host: 'example.com'
}
}
instead what I get is
// current link object
{
id: 3,
name: 'My test link',
'domain.id': 23,
'domain.host': 'example.com'
}
So nested objects aren't mapping correctly.
UPDATE
I have found nest options in query() documentation but setting nest: true doesn't seems to have any effect.
Changed Query
const links = await sequelize.query(query.trim(), {
type: sequelize.QueryTypes.SELECT,
model: Link,
mapToModel: true,
nest: true, // doesn't have any effect
});
For me nest worked only in conjunction with raw:
const links = await sequelize.query(query.trim(), {
type: sequelize.QueryTypes.SELECT,
model: Link,
mapToModel: true,
nest: true,
raw: true // Without this `nest` hasn't effect, IDK why
});
I have run into the same problem. My solution was:
return sequelize.query(/* query */, {
nest: true,
type: sequelize.QueryTypes.SELECT
});
As you see, you should not set mapToModel prop, just nest and type.
You can install dottie yourself, which is what nest: true is supposed to be doing (https://github.com/mickhansen/dottie.js):
import dottie from 'dottie';
// ...
const formattedLinks = links.map(l => dottie.transform(l.toJSON()))
It seems that raw queries with nest:true doesn't works with mapToModel. So the only way I found is to include nest:true, map with Link.build(link) and { include: Domain} option:
const query = `SELECT
links.name, links.type, links.code, links.originalUrl,
domains.id as 'domain.id', domains.host as 'domain.host',
count(
CASE WHEN hits.datetime > "${past}" AND hits.datetime <= "${now}" = true then 1 END
) as hitCount
FROM links
LEFT JOIN hits ON links.id = hits.linkId
LEFT JOIN domains ON links.domainId = domains.id
WHERE links.userId = ${req.user.id}
GROUP BY links.id, hits.linkId
ORDER BY hitCount DESC
LIMIT 5`;
const links = (await sequelize.query(query.trim(), {
nest: true,
type: sequelize.QueryTypes.SELECT,
}));
links.map((link) => Link.build(link, {include: Domain}))
As far as I can see the Link model has one domain with association so you will need to pass
include: <domain model> to map to domain model.
have a look at this : https://github.com/sequelize/sequelize/issues/1830

ExtJS creating record from existing store

I have created an ext store like so:
var store = new Ext.data.JsonStore({
root: 'vars',
fields: [{ name: 'rec_id', mapping: 'rec' }, { name: 'identity', mapping: 'id'}]
});
This works alright when I add data to the store via loadData(); and some json which looks like:
{ vars : {rec: '1', id:'John'} }
My problem is that if I use add(); to get this record into the store I have to first create it as an Ext.data.Record object.
I do this as pointed out here: https://stackoverflow.com/a/7828701/1749630 and it works ok.
The issue I have is that the records are entered with their mapped parameters rather than the ones I set. I.e, 'rec_id' becomes 'rec' and 'identity' becomes 'id'.
What am I doing wrong here?
You need to do the mapping manually, something like this:
var myNewRecord = new store.recordType({
rec_id: vars.rec,
identity: vars.id
});
store.add(myNewRecord);

IndexedDB and many-to-many Relationships

How are you all handling many-to-many relationships in IndexedDB?
For example, say I have a Blog object to hold a blog post and a Tag object for a tag/label of the blog post. One Blog can have many Tags and one Tag can be used by many Blogs.
I would create a blog store and tag store (though I'm open to suggestions) to house the two types of objects:
// ...
var blogStore = db.createObjectStore("blog", {keyPath: "blogId", autoIncrement: true});
blogStore.createIndex("title", "title", {unique: true});
var tagStore = db.createObjectStore("tag", {keyPath: "tagId", autoIncrement: true});
tagStore.createIndex("label", "label", {unique: true});
Off hand I can think of two ways to link the two:
have a Blog.tags which would be an array of BlogTag objects which holds blogId and tagId (and would also be in the store for retrieval) or
have a Blog.tags which would be an array of tagIds that could be used to look up the Tags.
The first way seems longer-winded but is how this would be tackled in SQL. Is that just SQL-baggage that I should leave behind?
I suppose a 3rd way would be to have Blog.tags be an array of Tags. This seems simplest but then I couldn't query for Tags or reuse tags across blogs (or could I?).
Has anyone else handled such a situation with indexedDB? If so, what did you end up doing? What were some pitfalls?
I'm working on an IndexedDB-backed JS neural network implementation and faced this very
problem.
We don't have joins in IndexedDB so you're looking at at least two object store hits unless you're doing some sort of memoization/caching.
From experience I've found that a document-oriented style is best with IndexedDB objects (store everything in the same store), but a secondary store is needed to house relations.
Here's what I'm doing.
Say you want to have a local store of actors and movies -- something like IMDB. This and most any many-to-many relationship can be modeled with IndexedDB using two tables: Objects and Relationships.
Here are the two tables. You'd want key lookups* on almost everything. Anything that doesn't say unique can be non-unique.
Objects object store:
type_id*
whatever*..
Relationships object store:
id* (unique, auto-incrementing)
from_type*
to_id*
An actor/movie example would be two records in the Objects table and one in the relationship table:
var actor1 = {
id: 'actor_jonah_goldberg',
display: 'Jonah Goldberg',
};
var actor2 = {
id: 'actor_michael_cera',
display: 'Michael Cera'
};
var movie1 = {
id: 'movie_superbad',
display: 'Superbad',
year: 2007
};
var movie2 = {
id: 'movie_juno',
display: 'Juno',
year: 2007
};
//relationship primary key ids are auto-inc
var relationship1 = {
from_id: 'actor_jonah_goldberg',
to_id: 'movie_superbad'
}
var relationship2 = {
from_id: 'actor_michael_cera',
to_id: 'movie_superbad'
}
var relationship3 = {
from_id: 'actor_michael_cera',
to_id: 'movie_juno'
}
Psuedo-code for getting Michael Cera's movies:
IndexedDBApp( { 'store': 'relationships', 'index': 'from_id', 'key': 'actor_michael_cera', 'on_success': function( row ) {...} );
// Would return movie_superbad and movie_juno rows on_success
Psuedo-code for getting all movies from a given year:
IndexedDBApp( { 'store': 'objects', 'index': 'year', 'key': 2007, 'on_success': function( row ) {...} );
// Would return movie_superbad and movie_juno rows on_success
Psuedo-code for getting a movie's actors:
IndexedDBApp( { 'store': 'relationships', 'index': 'to_id', 'key': 'movie_superbad', 'on_success': function( row ) {...} );
// Would return actor_jonah_goldberg and actor_michael_cera on_success
Psuedo-code for getting all actors:
IndexedDBApp( { 'store': 'relationships', 'index': 'id', 'cursor_begin': 'actor_a', 'cursor_end': 'actor_z', 'on_success': function( row ) {...} );
// Would return actor_jonah_goldberg and actor_michael_cera on_success

Categories