Slug Is Not Working While Importing External Data (MongoDB Database)
6 replies
Last updated: Feb 15, 2021
P
Hello, Slug is not working while importing external data (MongoDB database). I am following the guide “Importing data from external data into Sanity”. Everyting works fine, exept for generating slug. This slug exists in my schema, but does not exist in the external data.{
name: "slug",
title: "Slug",
type: "slug",
options: {
source: "title",
},
}
Now I am trying to generate the slug from the "title" of the external data, while executing a slugify function on that "title". Obviously this leads to using the wrong _type: "string", instead of _type: "slug". What can I do to solve this?
name: "slug",
title: "Slug",
type: "slug",
options: {
source: "title",
},
}
Now I am trying to generate the slug from the "title" of the external data, while executing a slugify function on that "title". Obviously this leads to using the wrong _type: "string", instead of _type: "slug". What can I do to solve this?
Feb 15, 2021, 1:55 PM
P
Hi Pieter, sounds like you're making good progress on the migration from MongoDB. For the slug, is it helpful to know that the generation function only works inside the studio? It gives you a 'Generate' button that you can use to generate a slug from the source field,
To generate slugs during import, you will need to replicate the functionality of the slug field. Our own slug function uses
titlein this case.
To generate slugs during import, you will need to replicate the functionality of the slug field. Our own slug function uses
speakingurlunder the hood: https://github.com/pid/speakingurl . Here's the function itself as an example: https://github.com/sanity-io/sanity/blob/ebd72b17236d29f6dad636c17e3ddd1b301e0853/[…]ackages/%40sanity/form-builder/src/inputs/Slug/utils/slugify.ts
Feb 15, 2021, 3:20 PM
P
Thnx for your reply!I think apart from the slugify function there is also the wrong type involved.
You think, my own simple slugify function would not work?
Here it is:
(to transform the data I am using node-json-transform)
var baseMap = {
item: {
_id: "_id",
title: "title",
slug: "title",
},
operate: [
{
run: function slugify(text) {
return text
.toString()
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/\.+/g, "")
.replace(/’+/g, "-")
.replace(/â+/g, "a")
.replace(/'+/g, "-");
},
on: "slug",
},
],
};
Transaction:
fetch(apiURL)
.then((res) => res.json())
.then((res) => transform(res, baseMap))
.then ... transaction.createOrReplace(document)
This results in "content has invalid type"
You think, my own simple slugify function would not work?
Here it is:
(to transform the data I am using node-json-transform)
var baseMap = {
item: {
_id: "_id",
title: "title",
slug: "title",
},
operate: [
{
run: function slugify(text) {
return text
.toString()
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/\.+/g, "")
.replace(/’+/g, "-")
.replace(/â+/g, "a")
.replace(/'+/g, "-");
},
on: "slug",
},
],
};
Transaction:
fetch(apiURL)
.then((res) => res.json())
.then((res) => transform(res, baseMap))
.then ... transaction.createOrReplace(document)
This results in "content has invalid type"
Feb 15, 2021, 4:48 PM
P
Have you tried setting
_type: "slug"(mind the underscore
_in front of
type) on the item?
Feb 15, 2021, 4:51 PM
P
Brilliant, it works!I have been playing with that option.
But forgot to set the "current" property (instead of "name").
slug: {
current: "title",
},
I also struggled a lot with nested data.
That is where node-json-transform comes in handy.
You should mention this of some sort in the docs about importing external data, I think.
Besides I like Sanity a lot!
Cheers.
But forgot to set the "current" property (instead of "name").
slug: {
current: "title",
},
I also struggled a lot with nested data.
That is where node-json-transform comes in handy.
You should mention this of some sort in the docs about importing external data, I think.
Besides I like Sanity a lot!
Cheers.
Feb 15, 2021, 5:52 PM
P
Awesome! And thanks - that's great feedback! Admittedly, there's not that much material yet on how to import external data, and I think you're one of the first people I've seen that undertake this from MongoDB to Sanity. We can definitely extend the documentation there.
Happy you're able to move on
🙂
Happy you're able to move on
🙂
Feb 15, 2021, 6:03 PM
P
Welcome.You are problably going to need some method to add unique id's too.
Here is how I did the job, totally:
const sanityClient = require("@sanity/client");
const fetch = require("node-fetch");
const { transform } = require("node-json-transform");
const crypto = require("crypto");
function unique() {
const uniqueid = crypto.randomBytes(16).toString("hex");
return uniqueid;
}
const client = sanityClient({
projectId: <projectId>,
dataset: "production",
token: <token>,
useCdn: false,
});
const apiURL = <apiURL>;
var baseMap = {
item: {
_id: "_id",
title: "title",
slug: {
current: "title",
},
dish: {
_ref: "dish._id",
},
tag: "tags",
freshItems: "fresh",
stockItems: "stock",
directions: "directions",
relatedRecipes: "related",
cookbook: {
_ref: "book._id",
},
info: "info",
},
each: function (item) {
item._type = "recipe";
item.slug._type = "slug";
item.dish._type = "reference";
item.book._type = "reference";
return item;
},
operate: [
{
run: function (ary) {
return transform(ary, nestedTag);
},
on: "tag",
},
{
run: function (ary) {
return transform(ary, nestedFresh);
},
on: "fresh",
},
{
run: function (ary) {
return transform(ary, nestedStock);
},
on: "stock",
},
{
run: function (ary) {
return transform(ary, nestedDirections);
},
on: "directions",
},
{
run: function (ary) {
return transform(ary, nestedRelated);
},
on: "related",
},
{
run: function slugify(text) {
return text
.toString()
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/\.+/g, "")
.replace(/’+/g, "-")
.replace(/â+/g, "a")
.replace(/'+/g, "-");
},
on: "slug.current",
},
],
};
var nestedTag = {
item: {
_ref: "_id",
},
each: function (item) {
item._type = "reference";
item._key = unique();
return item;
},
};
var nestedFresh = {
item: {
_id: "_id",
name: "name",
quantity: "quantity",
unit: "unit",
ingredient: "ingredient",
},
each: function (item) {
item._type = "ingredient";
item._key = unique();
return item;
},
};
var nestedStock = {
item: {
_id: "_id",
name: "name",
quantity: "quantity",
unit: "unit",
ingredient: "ingredient",
},
each: function (item) {
item._type = "ingredient";
item._key = unique();
return item;
},
};
var nestedDirections = {
item: {
_id: "_id",
name: "name",
},
each: function (item) {
item._type = "list";
item._key = unique();
return item;
},
};
var nestedRelated = {
item: {
_ref: "_id",
},
each: function (item) {
item._type = "reference";
item._key = unique();
return item;
},
};
fetch(apiURL)
.then((res) => res.json())
.then((res) => transform(res, baseMap))
.then((documents) => {
let transaction = client.transaction();
documents.forEach((document) => {
transaction.createOrReplace(document);
});
return transaction.commit();
});
Here is how I did the job, totally:
const sanityClient = require("@sanity/client");
const fetch = require("node-fetch");
const { transform } = require("node-json-transform");
const crypto = require("crypto");
function unique() {
const uniqueid = crypto.randomBytes(16).toString("hex");
return uniqueid;
}
const client = sanityClient({
projectId: <projectId>,
dataset: "production",
token: <token>,
useCdn: false,
});
const apiURL = <apiURL>;
var baseMap = {
item: {
_id: "_id",
title: "title",
slug: {
current: "title",
},
dish: {
_ref: "dish._id",
},
tag: "tags",
freshItems: "fresh",
stockItems: "stock",
directions: "directions",
relatedRecipes: "related",
cookbook: {
_ref: "book._id",
},
info: "info",
},
each: function (item) {
item._type = "recipe";
item.slug._type = "slug";
item.dish._type = "reference";
item.book._type = "reference";
return item;
},
operate: [
{
run: function (ary) {
return transform(ary, nestedTag);
},
on: "tag",
},
{
run: function (ary) {
return transform(ary, nestedFresh);
},
on: "fresh",
},
{
run: function (ary) {
return transform(ary, nestedStock);
},
on: "stock",
},
{
run: function (ary) {
return transform(ary, nestedDirections);
},
on: "directions",
},
{
run: function (ary) {
return transform(ary, nestedRelated);
},
on: "related",
},
{
run: function slugify(text) {
return text
.toString()
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/\.+/g, "")
.replace(/’+/g, "-")
.replace(/â+/g, "a")
.replace(/'+/g, "-");
},
on: "slug.current",
},
],
};
var nestedTag = {
item: {
_ref: "_id",
},
each: function (item) {
item._type = "reference";
item._key = unique();
return item;
},
};
var nestedFresh = {
item: {
_id: "_id",
name: "name",
quantity: "quantity",
unit: "unit",
ingredient: "ingredient",
},
each: function (item) {
item._type = "ingredient";
item._key = unique();
return item;
},
};
var nestedStock = {
item: {
_id: "_id",
name: "name",
quantity: "quantity",
unit: "unit",
ingredient: "ingredient",
},
each: function (item) {
item._type = "ingredient";
item._key = unique();
return item;
},
};
var nestedDirections = {
item: {
_id: "_id",
name: "name",
},
each: function (item) {
item._type = "list";
item._key = unique();
return item;
},
};
var nestedRelated = {
item: {
_ref: "_id",
},
each: function (item) {
item._type = "reference";
item._key = unique();
return item;
},
};
fetch(apiURL)
.then((res) => res.json())
.then((res) => transform(res, baseMap))
.then((documents) => {
let transaction = client.transaction();
documents.forEach((document) => {
transaction.createOrReplace(document);
});
return transaction.commit();
});
Feb 15, 2021, 8:11 PM
Sanity– build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.