Imaging we have documents like this:
{
_id: ObjectId(""),
accountId: ObjectId(""),
userId: ObjectId(""),
someOtherFieldA: ["some", "array", "values"],
someOtherFieldB: ["other", "array", "values"],
...
}
Furthermore there are multiple compound indices, ex.:
{ userId: 1, someOtherFieldA: 1, ... }
{ userId: 1, someOtherFieldB: 1, ... }
We want to shard by accountId.
Would it be enough to add a single field index for accountId, so that the existing indices still work? Or would all indices need the accountId as prefix (first part)?
When you run the sh.shardCollection() command then MongoDB automatically creates an index on the shard key field (unless such an index exist already), so you don't need to care about this question.
Related
I have a MongoDB index:
Reservation.index(
{
source: 1,
accountID: 1, // <-- This is the only required field
confirmationCode_1: 1,
confirmationCode_2: 1,
confirmationCode_3: 1
},
{name: "Unique_reservation_index_1", unique: true}
);
Here are some sample entries I have in the database and I want to make sure that duplicates can't be made:
[
{
source: "A",
accountID: "AAA",
confirmationCode_1: "ABC"
},
{
source: "B",
accountID: "BBB",
confirmationCode_1: "ABC"
confirmationCode_2: "DEF"
},
{
source: "C",
accountID: "CCC",
confirmationCode_3: "GHI"
}
]
Sometimes I have confirmationCode_1 set and not confirmationCode_2 other times I both confirmationCode_1 and confirmationCode_2 set. Other times I have confirmationCode_3 set.
I want MongoDB to allow me to have the following doc (missing the confirmationCode_2 and confirmationCode_3 fields). Will it let me with the above index?
{
source: "A",
accountID: "123",
confirmationCode_1: "ABC"
}
Will it prevent me from adding two similar docs with confirmationCode_2 not defined or will that be considered the same? For example, if it does allow the above doc, will this be prevented?
{
source: "A",
accountID: "AAA",
confirmationCode_1: "ABC_2"
}
If I don't supply the confirmationCode_2 field, does it set the confirmationCode_2 field to null?
If I change the unique index to include sparse: true, how will it act differently?
Reservation.index(
{
source: 1,
accountID: 1, // <-- This is the only required field
confirmationCode_1: 1,
confirmationCode_2: 1
},
{name: "Unique_reservation_index_1", unique: true, sparse: true}
);
From MongoDB document on unique Index,
A unique index ensures that the indexed fields do not store duplicate values
undefined / empty / null field is allowed as long as you do not have the same tuple of values of the fields in the compound index.
Below is my actual testing result:
You can observe that the document is successfully added under the unique index.
Will unique indexes ignore fields that don't exist?
No, the index will store a null value for this field, MongoDB will enforce uniqueness on the combination of the index key values.
//You have this docuemt on you MongoDB
{
source: "A",
accountID: "123",
confirmationCode_1: "ABC"
}
//You try to insert the next document, note the missing "accountID" field
//Even though "source" and "confirmationCode_1"
//This operation SUCCESS because
//MongoDB will enforce uniqueness on the "combination" of the index key values
{
source: "A",
confirmationCode_1: "ABC"
}
//You try to insert the next document
//The operation FAIL to insert the document
//because of the violation of the unique constraint
//on the combination of key values
{
source: "A",
accountID: "123",
confirmationCode_1: "ABC"
}
What if you change unique: true to unique: true, sparse: true ?
An index that is both sparse and unique prevents collection from
having documents with duplicate values for a field but allows multiple
documents that omit the key.
I need an index that will provide me uniqueness of the field among all fields. For example, I have the document:
{
_id: ObjectId("123"),
fieldA: "a",
fieldB: "b"
}
and I want to forbid insert the document
{
_id: ObjectId("456"),
fieldA: "new value for field a",
fieldB: "a"
}
because already exists the document that has the value "a" set on field "fieldA". Is it possible?
It seems you need a multikey index with a unique constraint.
Take into account that you can only have one multikey index in each collection for this reason you have to include all the fields you like to uniqueness inside an array
{
_id: ObjectId("123"),
multikey: [
{fieldA: "a"},
{fieldB: "b"}
]
}
Give a try to this code
db.collection.createIndex( { "multikey": 1}, { unique: true } )
To query you have to code
db.collection.findOne({"multikey.fieldA": "a"}, // Query
{"multikey.fieldA": 1, "multikey.fieldB": 1}) // Projection
For more info you can take a look at embedded multikey documents.
Hope this helps.
another option is to create a document with each unique key, indexed by this unique key and perform a loop over the field of each candidate document cancelling the write if any key is found.
IMO this solution is more resource consuming, in change it gets you a list of all keys consumed in written documents.
db.collection.createIndex( { "unikey": 1}, { unique: true } )
db.collection.insertMany( {[{"unikey": "$FieldA"},{"unikey": "$FieldB"}]}
db.collection.find({"unikey": 1})
Suppose, I have the following database:
{
_id: 1,
name: 'Alice',
courses: [
{
_id: 'DB103',
credits: 6
},
{
_id: 'ML203',
credits: 4
}
]
},
{
_id: 2,
name: 'Bob',
courses: []
}
I now want to 'upsert' the document with the course id 'DB103' in both documents. Although the _id field should remain the same, the credits field value should change (i.e. to 4). In the first document, the respective field should be changed, in the second one, {_id: 'DB103', credits: 4} should be inserted into the courses array.
Is there any possibility in MongoDB to handle both cases?
Sure, I could search with $elemMatch in courses for 'DB103' and if I haven't found it, insert, otherwise update the value. But these are two steps and I would like to do both in just one.
I'm a new user of mongodb and I have a model like below. For update list data, I have to specify the element in an array. So I think I need to store a unique value for each element. Because list.name and list.price are variable data.
So are there any good ways to create an unique id in mongodb? Or should I create unique ids by myself?
{
name: 'AAA',
list: [
{name: 'HOGE', price: 10, id: 'XXXXXXXXXX'}, // way to add id
{name: 'FUGA', price: 12, id: 'YYYYYYYYYY'} // way to add id
]
}
Mongodb creates unique id only for documents. There is no better way for list or array elements. So, you should create Unique ids yourself.
Add keep in mind that, While updating your list use $addToSet.
For more information of $addToSet follow this documentation
use ObjectId() on your id field, so like..
db.test.update({name: "AAA"}, { $push: { list: {_id : ObjectId(), name: "dingles", price: 21} }});
reference: https://docs.mongodb.org/v3.0/reference/object-id/
whoever is seeing this in 2022, mongodb creates unique ids automatically we just have to provide schema for that particular array.
like,
_id : {
type: String
},
list: {
type: [{
Name : {
type: String
},
price : {
type: String
}
}]
}
this schema will generate auto id for all elements added into array
but below example will not create it.
_id : {
type: String
},
list: {
type: Array
}
I have two collections, customSchemas, and customdata. Besides the default _id index, I've added the following indexes
db.customData.createIndex( { "orgId": 1, "contentType": 1 });
db.customSchemas.createIndex( { "orgId": 1, "contentType": 1 }, { unique: true });
I've decided to enforce orgId on all calls, so in my service layer, every query has an orgId in it, even the ones with ids, e.g.
db.customData.find({"_id" : ObjectId("557f30402598f1243c14403c"), orgId: 1});
Should I add an index that has both _id and orgId in it? Do the indexes I have currently help at all when I'm searching by both _id and orgId?
MongoDB 2.6+ provides index intersection feature that cover your case by using intersection of index _id {_id:1} and index prefix orgId in { "orgId": 1, "contentType": 1 }
So your query {"_id" : ObjectId("557f30402598f1243c14403c"), orgId: 1} should be covered by index already.
However, index intersection is less performant than a compound index on {"_id" : 1, orgId: 1}, as it comes with an extra step (intersection of the two sets). Hence, if this is a query that you use most of the time, creating the compound index on it is a good idea.