Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Natetronn/9bafd1722a2b67b9bf4528e45992baa2 to your computer and use it in GitHub Desktop.
Save Natetronn/9bafd1722a2b67b9bf4528e45992baa2 to your computer and use it in GitHub Desktop.
Directus Flow for Multiple Unique Indexes

Directus Flow for Multiple Unique Indexes

Context:

  • owners collection

  • sellers collection

  • countries collection

  • shipping_rates collection

    • Fields:

      • seller_id: Many-to-One Relationship Field -> Sellers (key = seller_id)

      • country_id: Many-to-One Relationship Field -> Countries (key = country_id)

      • shipping_rate: Input Field (for shipping rate)

Sellers are only assigned one shipping rate per country.

For example:

  • Assume there are currently two sellers in the sellers collection; Seller A and Seller B.

  • Assume two countries are currently available in countries collection; Egypt and United States.

  • Assume an owner can add shipping_rates to sellers.

  • Owner creates two shipping rates. One rate is Seller A, Egypt, $5 and another rate of Seller A, United States, $6 (two items now created in shipping_rates collection for Seller A.)

  • Once both Shipping Rates are created for the two Countries, owner should try to add a third shipping rate to Seller A, for either Egypt or United States, resulting in an error being thown and error message displayed in a modal.

  • Same scenario for owner creating shipping rates for Seller B and so on.

Basically, only one shipping rate, per country AND per seller is allowed.

Create New Flow -> Event Hook -> Filter (Blocking)

2023-09-20-23-37-36-image

Note: do not select a Response Body, leave it blank.

Read Data operation (key: unique_indexes)

2023-09-20-23-39-37-image

{
  "filter": {
    "seller_id": {
      "_eq": "{{ $trigger.payload.seller_id }}"
    },
    "country_id": {
      "_eq": "{{ $trigger.payload.country_id }}"
    }
  }
}

Note: we use this query to check if seller_id and country_id both already exists.

Run Script operation (key: script)

2023-09-20-23-45-54-image

module.exports = async function (data) {
  return { output: data.unique_indexes.length === 0 ? true : false };
};

Note: checking unique_indexes array if it's empty return { output: true } else return { output: false }

unique_indexes comes from previous Read Data operation's key.

Update: the following steps can be removed if you do the following in the Run Script Operation^: https://gist.github.com/Natetronn/9bafd1722a2b67b9bf4528e45992baa2?permalink_comment_id=4762238#gistcomment-4762238

Condition operation

2023-09-20-23-46-31-image

{
  "script": {
    "output": {
      "_eq": true
    }
  }
}

Note: script is the key from the previous operation's and output is the object key from the returned value of its code. If condition is true create item (don't block). If condition is false run script to throw error; payload isn't passed and item isn't created; instead an error modal is displayed with the throw new error message.

Run Script (throw_error):

2023-09-20-23-47-26-image

module.exports = async function (data) {
  throw new Error("This country already exists, add another one!");
  return {};
};

The Completed Flow:

2023-09-20-23-48-14-image

@Natetronn
Copy link
Author

Natetronn commented Sep 21, 2023

This is in response to no composite key support currently in Directus.

We're using a Flow to avoid the creation of an extension; as cube-dan suggested in the same discussion here.

The following discussion assisted in checking for empty payload array.

@Natetronn
Copy link
Author

Natetronn commented Sep 21, 2023

A cooperative effort by Abdallah-Awwad and myself.

@BeSaRa
Copy link

BeSaRa commented Oct 4, 2023

great !!!

@BI-MarcB
Copy link

Hello there, thank you for this great example. As we will be using this a lot in our instance. I had a look at reducing the complexity of the flow.
I was able to remove the last condition and run_script instance, by putting the check directly into the first script instance:

module.exports = async function (data) {
    if (data.unique_indexes.length !== 0) {
  		throw new Error("An entry for this key already exists (duplicate).");
    }
}

My flow looks like this now:
grafik

In my test, this achieved the same output.

@Abdallah-Awwad
Copy link

Hello there, thank you for this great example. As we will be using this a lot in our instance. I had a look at reducing the complexity of the flow. I was able to remove the last condition and run_script instance, by putting the check directly into the first script instance:

module.exports = async function (data) {
    if (data.unique_indexes.length !== 0) {
  		throw new Error("An entry for this key already exists (duplicate).");
    }
}

My flow looks like this now: grafik

In my test, this achieved the same output.

That actually makes more sense, thanks for sharing!

@Natetronn
Copy link
Author

@BI-MarcB nice! That simplifies it a bit, thanks for sharing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment