Avoid Duplicates in dataset using Hook, Filter, Query & beforeInsert Function

I’m trying to use a dataset hook on our Irish Whiskey Club inputs in order to avoid adding duplicates from a members inputs when they click on the submit button (that is, if they enter the same Whiskey more than once it doesn’t get saved in the dataset). The dataset (:Clubinput") has the “Whiskey” name in column 1, the “Date” in column 2 and “Comments” in column 3. The “Clubinput” dataset has the inputs from all the members, so I need to filter the dataset by “currentUser” before doing a query on “Whiskey” in the code. Then I need to check for a duplicate before inserting their new entry’s into the dataset.

My current code always returns the errors:
save operation failed: TypeError: _wixData2.default.filter(…).eq(…) is not a function
_wixData2.default.filter(…).eq(…) is not a function

Clearly, I have something incorrect!

//Here's my data.js code.
import wixData from 'wix-data';
import wixUsers from 'wix-users-backend';
export function searchForDuplicates(value) {
return (wixData.filter("Clubinput")
.eq("ID", wixUsers.currentUser))
(wixData.query("Clubinput")
.eq("Whiskey", value) 
.find()
.then((results) => {
return results.items.length;
})
.catch((err) => {
let errorMsg = err;
})
)}
export function Clubinput_beforeInsert(item) {
return searchForDuplicates(item.Whiskey)
.then((res) => {
if(res > 0) {   
return Promise.reject("Duplicate");
}
return item;
});
}

You should not mix .filter() and .query() together.
“filter” is for data set s while “query” directly queries the collection.

As J.D. as already mentioned above, you can’t edit this tutorial to have it filtered before querying it for duplicates.
https://www.wix.com/corvid/forum/corvid-tips-and-updates/example-no-database-duplicates

Thanks for the information! It helped point me in the right direction, eventually!

This code appears to work!

//
import wixData from 'wix-data';
import wixUsers from 'wix-users-backend';
export function searchForDuplicates(value) {
  return wixData.query("Clubinput")
      .eq("Whiskey", value)
      .and(wixData.query("Clubinput")
          .eq("Owner", wixUsers.currentUser.Owner))
      .find()
      .then((results) => {
      return results.items.length;
      })
      .catch((err) => {
      let errorMsg = err;
 });
 }
                                              
 export function Clubinput_beforeInsert(item) {
   return searchForDuplicates(item.Whiskey).then((res) => {
       if(res > 0) {   
       return Promise.reject("Duplicate");
       }
       return item;
 });
 }

Uggg…. further testing indicates that all entries are being rejected…back to the drawing board!

A few comments

  1. No need to have “export” before the searchForDuplicates() function.
  2. No need to use .and() in the query. You can do:
return wixData.query("Clubinput")
      .eq("whiskey", value)
      .eq("owner", wixUsers.currentUser.owner)
      .find()
  1. No need to use wix-users-backend. You can pass the userId from the hook context. See:
    https://www.wix.com/corvid/reference/wix-data.Hooks.html#HookContext

  2. If you meant to use the system owner field, so it should be “_owner” (but maybe you meant to your own custom field).

  3. You used “Whiskey” as the field key, but a field key can never start with an upper-case letter, so there must be a mistake. The same for the Owner field. It cannot start with a capital O.

@jonatandor35 Thanks JD! When I read about using query, it wasn’t clear to me in the description to use the field name or field key. Even looking at several examples that do this for just one condition it wasn’t clear to me. I’m getting ready to try it again. I still think I need to use the ”and” qualifier tho, because I need both items to match in the collection row before declaring a duplicate. I’ll let you know if (when) I get it working! I appreciate the help! Last time I did any real coding was in FORTRAN! Yup…I’m old! :slight_smile: Learning new things is fun, but sometimes can be frustrating.

Oh, I see what you mean about “and” now! The ”and” is always implied with two “eq”!

@jonatandor35 One further question… In the call to “searchForDulicates”, I have “item.Whiskey”. This is supposedly coming from a drop down list on the page where the list comes from a different dataset to be written to “Clubinput”. Again, “Whiskey” is the field name not the field key. Should this be the field key in “Clubinput”?

@terrancehudson
J.D. already covered that in his previous reply to you about using the field key.

…You used “Whiskey” as the field key, but a field key can never start with an upper-case letter, so there must be a mistake. The same for the Owner field. It cannot start with a capital O.

Change it to the field key and it should all be good to go.

@givemeawhisky Yup…figured that, but wanted to ask anyway. Thanks! Learning Corvid & js faster thanks to you guys!

@terrancehudson
Thanks go to J.D. for this one. :+1:
Although you mention whisky and that is making me feel a bit thirsty :tumbler_glass::wink:

Hot dog! I tested this code a couple times now and it seems to be working!!!

@GOS : When we get this set up on the official site (cabbageshed.com) you should come in and join the club!!!

@J.D.: It didn’t like the “wixUsers.currenUser.id” unless I included the import line.

import wixData from 'wix-data';
import wixUsers from 'wix-users-backend';
function searchForDuplicates(value) {
return wixData.query("Clubinput")
    .eq("title", value)
    .eq("_owner", wixUsers.currentUser.id)
    .find()
    .then((results) => {
    return results.items.length;
     })
    .catch((err) => {
    let errorMsg = err;
   });
   }
   export function Clubinput_beforeInsert(item) {
     return searchForDuplicates(item.title).then((res) => {
     if(res > 0) {   
     return Promise.reject("Duplicate");
     }
    return item;
  });
  }

You don’t need to use wixUsers.currentUser.id

You can do something like:

function searchForDuplicates(value, userId) {
return wixData.query("Clubinput")
    .eq("title", value)
    .eq("_owner", userId)
    .find()
//etc....
//...
//...
export function Clubinput_beforeInsert(item, context) {
     return searchForDuplicates(item.title, context.userId).then((res) => {
//etc...

and no need to import wixUsers.