Contentful: How to get an entry using nothing but one of its fields? Or, how to set the entryId in web app? - contentful

I am needing to make some sharable blog post URLs. To do that, the URL must be something like webpage.com/blog-post-title. It cannot be webpage.com/5GFd5GDSg2345WD.
Since I am using dynamic routing, I need to get a Contentful entry using nothing but what is on the URL. There should not be any queries because queries are ugly and reduce shareability, like webpage.com/blog-post-title?query=queriesAreUgly.
Unfortunately, I need the entryId to get the entry. Also unfortunately, the entryIds are all very ugly and therefore completely useless/unusable. I wish I could set my own entryId, but this does not appear to be possible for mysterious reasons.
I could make a lookup table that pairs URLs with entryIds, but I'm going to be handing this contentful project to someone who is not tech savy, and they should not have to manage a lookup table.
I could get all blog entries then filter by blog title, but, very obviously, this is inefficient, as I would be loading thousands of lines of text for no reason at all.
I could create my own backend API and doing all this myself, but this is also a bad solution because it would take too much time and I could not give it to my non-tech-savvy client.
There are seemingly no solutions to this problem which created by Contentful's inherent needless inflexibility.
The only efficient way to get this to work is to find the entry not by its ID but by one of its fields. Is there a performant/efficient way to do this, or am I just going to have to filter through every single blog post until I find the one with the correct title?

How about adding a 'slug' field to the blog post content type, which you can auto-generate from the title using the field settings (so you don't have to type it out manually?)
You can then filter on the slug field in the query.
If you're using the JavaScript SDK (which it sounds like you are), you can use getEntries() and filter by the slug field to get a single blog post. Like so:
import { createClient } from "contentful";
const client = createClient({
space: {SPACE_ID},
accessToken: {ACCESS_TOKEN},
});
const response = await client
.getEntries({
content_type: "blogPost",
limit: 1,
"fields.slug": "blog-post-title",
})
.then((entry) => entry)
.catch(console.error);

Related

Is it possible to pass the same variable to all render statements in Node.js?

I'm designing an ecommerce website using Node, Express and Pug. When a customer adds an item to their basket, I'd like to display a count of the items next to the basket icon which appears on every page. Like how I can say app.use(some_middleware_func) and have it apply to all routes, can I define a variable to be passed to all res.render('template', { data: some_data }) statements? The only way I can see of doing it is to manually include the information in the data object for each statement but that doesn't seem very maintainable.
Hopefully somebody has an idea or perhaps there is a much better way to approach this?

Best way to implement ACL with Mongoose

I have my data model already defined and implemented. I can very easily write manually the filter to filter out non-authorized results for the user who sent the query (which would be in the style of: "collection.acl.personId": queryPersonId )
My problem is, where and how should I write this "thing" to be as automatic as possible?
I tried to do it with a custom query and a static method, but did not had any luck on both.
Static method con: I don't want to rewrite all my code to use .then(). I want to keep the current chaining.
Custom query: it simply did not worked, even by following the doc.
Ideal the result would be something like
Model.findWithAcl(filters).lean()
Model.findOneWithAcl(filters).lean()
Note that we are using Typescript. The priority would be to have something working, but having the ability to have a working type would be the second priority right after.
Thanks for any help
Casl mongoose gives a very good way of filtering both results (row level) and fields from collections. Note that it also can be used in the front end.
Great package that works very well with auth0 rights.
https://casl.js.org/v5/en/guide/intro
https://casl.js.org/v5/en/package/casl-mongoose

Custom Geddy.js Model ID?

I have noticed in Geddy that when I create a model and a subsequent record for that model, I get a very ugly model ID associated with the record. Something like:
http://localhost:4000/posts/3FEEDE8D-2669-445B-AEA1-A31092A7FEDA
Is there a way to change this?
Ideally, I would always want this to be some sort of string. Where it be for a post or user:
http://localhost:4000/posts/this-is-a-post-title
http://localhost:4000/profile/meebix
If this is possible, how should I:
Configure routes
Change primary key for model
Other implementation steps I may need
Thanks!
Yes, you can change the id if you really want to, but you'll be going off the beaten path there, so it's quite a bad idea. Let Geddy handle IDs for you.
The way I would do this (and certainly how many others have too) is to have a "slugging" function create a slug from the post title, and save that in your database. Then, query on that instead in your show action. You won't have to change your routes.
This is what your query will look like in the show action:
Post.first({slug: params.id}, function (err, post) {
params.id is whatever string you use in the route /posts/<this string>
So once you change your show links to use the slug instead of the ID you will be all set!

ember.js rest api with pagination

At the moment I'm pointless how do achieve pagination with ember-data. I found out, that i can return 'meta' property in response and ember-data does not throw an error. But I just don't know how to access it, nor what is intended purpose of this property.
The few examples on internet assume that i have whole collection already loaded to ember, or they do little trick and do infinite scroll, which does'nt require information about page count.
I think that loading all records it's ok if I would have < 1k of them, but sometimes I'll be dealing with massive amounts of data (let's say apache logs). What then?
So basically I'm at the point in which I would like to use ember and ember-data to build my first real-life application, but I just think that it is not a good idea.
Ok, so anybody has any idea how to solve this basic, yet complicated, problem? :)
Ok, so here are some ideas to get you started.
First, you have to start with a route and take an page number as a dynamic parameter.
this.resource('posts', { path: '/posts/:page' };
Then as I have no experience with Silex, you need to support some kind of server side parameters that could be used for pagination. For example offset and limit where first means how many records you want to skip and second how many record you want in select from there. Ideally you should implement them as query parameters like ?offset=0&limit=10.
Then you just implement your table route as follows:
App.TableRoute = Ember.Route.extend({
model: function (params) {
return App.Post.find({ offset: (params.page - 1) * 10, limit: 10 });
}
});
You can then start doing some more magic and create your items per page parameter or validate the page number by fetching number of all records in advance.

Looking up types from Freebase

I am trying to find a list of relevant types to a certain string from Freebase, lets say for example i enter Jordan, then i will have a list with types country, person, athlete .. etc.
I have found several ways for the query, for example:
First Query
trying to get the JSON fails, using:
$.getJSON('http://api.freebase.com/api/service/search?query=jordan',function (data) {
console.log(data);
});
There is another query that gives me better result, as i only get the types here but i also cannot get the JSON file from it.
Will appreciate any help.
Your problem has probably less to do with freebase and more to do the fact that you can't do cross domain http requests. You are requesting data from api.freebase.com but you are probably hosting this page in another domain.
You can use the JSONP mechanism to circumvent that restriction, here is some documentation:
http://api.jquery.com/jQuery.getJSON/
Read the section JSONP.
Another couple of points:
Are you trying to search for all entities that somehow match the word "jordan" or are you looking for exactly all the entities that are named "jordan" ? Your best bet is to use the /search API instead of /mqlread which is for structured database queries.
You are also using the legacy API that is deprecated. Here is some docs on the new API:
http://wiki.freebase.com/wiki/API
Here's how your request will look (note that you 'll need an API key for production):
https://www.googleapis.com/freebase/v1/search?query=jordan&mql_output=[{%22name%22%20:%20null,%22type%22:[]}]

Resources