MongoDB failing to enforce unique constraints on partial indexes

I have a set of data that looks like this:

{
  name: "Acme co."
  add4: "",
  nationalNumber: "+13412768376"
}, {
  name: "Acme Inc.",
  add4: "6345",
  nationalNumber: ""
}

My goal is to insert these records into a collection, but only if they are unique. To determine uniqueness, I need to check for duplicates based on:

  1. nationalNumber (if the field is not empty or null)
  2. name + add4 (if both fields are not empty or null)

In my Node.js application, I have the following code:

 await db.collection('mergedcompany').createIndex(
      { nationalNumber: 1},
      { unique: true },
      { partialFilterExpression: {nationalNumber: {$exists: true}}}
      );

    await db.collection('mergedcompany').createIndex(
      { name: -1, add4: -1},
      { unique: true },
      { partialFilterExpression:{ name: {$exists: true}, add4: {$exists: true}}}
      );

I am looping through the records and inserting them using the following code:

try {
  await db.collection('mergedcompany').insertOne(record);
} catch (e) {
  sails.log.error(e);
}

However, all records are being inserted even when there are duplicate values as defined in the unique index. When I remove the "partial" filter from the index, MongoDB throws errors as expected. But with the partial filter included, no errors are thrown and all records are still inserted, regardless of duplicate data.

What steps should I take to resolve this issue?

Answer №1

Except for the syntax errors, this code is expected to function properly:

db.getCollection('mergedcompany').createIndex(
   { nationalNumber: 1 },
   { unique: true, partialFilterExpression: { nationalNumber: { $exists: true } } }
);

db.getCollection('mergedcompany').createIndex(
   { name: -1, add4: -1 },
   { unique: true, partialFilterExpression: { name: { $exists: true }, add4: { $exists: true } } }
);


db.getCollection('mergedcompany').insertOne({ name: "Acme co.", add4: "", nationalNumber: "+13412768376" });
db.getCollection('mergedcompany').insertOne({ name: "Acme co.", add4: "", nationalNumber: "+13412768376" });
WriteError({
   "index": 0,
   "code": 11000,
   "errmsg": "E11000 duplicate key error collection: so.mergedcompany index: nationalNumber_1 dup key: { nationalNumber: \"+13412768376\" }",
   "op": {
      "_id": ObjectId("601d74357aec96fa0da88319"),
      "name": "Acme co.",
      "add4": "",
      "nationalNumber": "+13412768376"
   }
})



db.getCollection('mergedcompany').insertOne({ name: "Acme Inc.", add4: "6345", nationalNumber: "" });
db.getCollection('mergedcompany').insertOne({ name: "Acme Inc.", add4: "6345", nationalNumber: "" });
WriteError({
    "index" : 0,
    "code" : 11000,
    "errmsg" : "E11000 duplicate key error collection: so.mergedcompany index: nationalNumber_1 dup key: { nationalNumber: \"\" }",
    "op" : {
        "_id" : ObjectId("601d74647aec96fa0da8831b"),
        "name" : "Acme Inc.",
        "add4" : "6345",
        "nationalNumber" : ""
    }
})

Please note that checking for

{ nationalNumber: { $exists: true }}
includes nationalNumber: "", resulting in a true condition. The field must be skipped entirely in this case.

Answer №2

Here's a solution that will function:

If the test document remains unchanged after the initial run, an error message will be triggered.

const mongoose = require("mongoose");

const schema = mongoose.Schema({
  name: {
    type: String,
    unique: true,
    required: true,
  },
  add4: {
    type: String,
    unique: true,
    required: true,
  },
  nationalNumber: {
    type: String,
    unique: true,
    required: true,
  },
});

const model = mongoose.model("unique", schema);

const testDocument = {
  name: "Acrhrme co.",
  add4: "th",
  nationalNumber: "+1341rr2h68376",
};

const insertFunc = async () => {
  try {
    await mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true });
    await model.create(testDocument);
  } catch (error) {
    console.error(error);
  }
};

insertFunc().catch(err => {
    console.error(err); 
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible for JavaScript to identify modifications in the HTML, like an input made with Ctrl+Shift+I?

Check out this website I'm currently working on. As a fun challenge for users, we're encouraging them to use ctrl+shift+i to manipulate the HTML and modify certain elements. Is it possible for Javascript or CSS/HTML to detect these changes? For ...

Sharing configurations between a Node.js application and client-side JavaScript

I am facing an issue where I need to use a config object in both my node app and browser. Below is the path and content of the configuration file: path: [app]/public/js/config.js content: var config = { "foo": "bar", "num": 42, "list": ["a" ...

Tips for displaying my libraries' function arguments while hovering in VSCode

As the creator of a JavaScript library, I am intrigued by how some libraries display function parameters and definitions when hovering over them in VSCode. Despite my efforts to add jsdoc style comments around the class definitions, I have not been able to ...

Trouble Arising from the Lack of Coordination Between CSS Transition and JavaScript Update Triggered by Element

I'm currently working on a web development project that involves a list of clickable elements. When one of these elements is clicked, it should become active and trigger a CSS transition (such as a transform) with a duration of 200ms. Additionally, I ...

I am currently working on completing my order book code, but I am struggling to understand how to summarize the objects

I have been working on my order book code and I am struggling to figure out how to summarize objects. Below is the current code that I have: const orderbook = [ { "ClientID": "31135d2c-a5f0-11ed-b07a-10e7c6f7c62e", "Side": "BID", ...

Stop objects from shifting while easily applying a border

I have a code that adds a red border around elements when you mouseover them and removes it when you mouseout. However, the elements jump around when the border is added because it changes their dimensions. Is there a way to stop this jumping behavior? ...

Failure to trigger jQuery.ajax success function on Windows XP operating system

Snippet: $.ajax({ type: "POST", url: "students/login", data:{"data[Student][email]":_email,"data[Student][password]":_password}, beforeSend: function(){ $("#confirm").text(""); }, error: function (xhr, status) { ale ...

Extension for Chrome that enhances YouTube video playback experience

I'm struggling to figure out why this isn't functioning. I've reviewed the Google extension dev docs and examined some sample code. Checked various Stack Overflow questions and answers, but haven't received any helpful feedback or res ...

Transfer the array using Ajax to a PHP script

I have an array generated using the .push function that contains a large amount of data. What is the most effective way to send this data to a PHP script? dataString = ??? ; // Is it an array? $.ajax({ type: "POST", url: "script.php" ...

Personalizing buttons on a carousel in React-bootstrap

I am facing an issue with my carousel and buttons placement. The buttons need to be outside of the carousel, but I'm unsure how to connect them effectively. React-Bootstrap's activeIndex option was suggested, but since my carousel is not cyclic l ...

CSS code for vertical navigation arrows to remain on both the left and right sides of the webpage

I'm struggling a bit with the CSS. I want to recreate the same effect as seen on . The left and right navigation arrows stay fixed vertically even when scrolling up or down the page. Does anyone have any code examples for that? ...

I find myself struggling to manage my javascript dependencies

Currently, I am utilizing NPM along with various angular packages. As per the tutorial on Basic Grid Part 1 at this link, I am encountering challenges. This is my file directory structure: D:/nodeStuff/uiGrid includes: node_modules uigrid.css uigrid.h ...

Having trouble sending data from the controller to the view in Laravel 8

I am struggling to display data retrieved from the database in my view through the controller. Despite trying various solutions found on similar questions, none of them seem to be effective. My main goal is to showcase a list of employees on my admin page. ...

Show only the selected option with jQuery's on change event and disable or remove the other options

My goal is to make it so that when a user selects an option from a dropdown menu, the other options are disabled or hidden. For example, if option "1" is selected, options "2", "3", and "4" will be removed: <div class="abc"> <div class="xyz"> ...

Overwriting the responseText from a previous XMLHttpRequest in JavaScript

I am working on updating two different JavaScript charts displayed on a PHP page by making sequential XMLHttpRequests using JavaScript. The goal is to update the data on these charts simultaneously. <!DOCTYPE HTML> <html> <head> <scri ...

Promises.all fails to reach the catch block after the initial rejection

I'm completely new to promises and I'm learning how to save multiple items to a MongoDB database system. When dealing with a single item, I have a function that utilizes promises. It returns a promise that either rejects if the database save ope ...

Discover and transform any strings that begin with http & https into clickable links

Can I use jQuery to search a paragraph for all strings that begin with http & https and turn them into clickable links? I have my Twitter feed displayed on my website, but any lines starting with http & https are shown as regular text. Is it feasible to t ...

How should a value be correctly retrieved from a separate function?

Let's say there is a function: function name(){ var first_name = "mike"; } The goal is to pass the value of first_name to another function. One way to do this is: function name(){ var first_name = "mike"; getName(first_name); } But what if y ...

SignalR gets stuck on the 'Initiating start request' screen, halting all progress

SignalR has been causing some strange behavior for me lately. After doing some refactoring, I started experiencing connectivity issues. It seems like my code was just lucky to work before because it didn't follow the recommended practices. For example ...

The Node.js express-generator application encounters a problem and is unable to start because of a TypeError: app.set function is not recognized

During the setup of my application using nodejs and express-generator, I encountered an issue when running the following commands in my terminal: npm install multer --save npm audit fix Afterwards, when I attempted to run node ./bin/www I received an err ...