Mongo compound index ordering [duplicate] - javascript

This question already has an answer here:
How can you specify the order of properties in a javascript object for a MongoDB index in node.js?
(1 answer)
Closed 8 years ago.
To define a compound index:
db.collection.ensureIndex( { orderDate: 1, zipcode: -1 } )
It suddenly dawned on me : are the fields of a JS object ordered?
Is there an implicit assumption that orderDate comes first? I'm quite surprised it doesn't use an array instead.
For mongoose, we use :
schema.index({a:1, b:1})
How can we ensure this object is transmitted to the mongo server with the fields ordered as specified in the code?
This post says fields are not ordered. Does JavaScript Guarantee Object Property Order?
Is it acceptable style for Node.js libraries to rely on object key order?

From the documentation
Indexes store references to fields in either ascending (1) or descending (-1) sort order. For single-field indexes, the sort order of keys doesn’t matter because MongoDB can traverse the index in either direction. However, for compound indexes, sort order can matter in determining whether the index can support a sort operation.
So if you created your index using
db.collection.ensureIndex( { orderDate: 1, zipcode: -1 } )
the object will be transmitted to the mongo server with the fields as ordered also note that using
db.collection.ensureIndex( { orderDate: 1, zipcode: -1 } )
and
db.collection.ensureIndex( { zipcode: -1 , orderDate: 1} )
will create two different compound indexes

Related

Fetch and sort mixed character from firebase javascript

Firebase Structure
Periods
+Period1
+Period10
+Period2
+Period3
+Period4
I am getting the value as it is. But i want to be sorted like Period1, Period2, Period3..,Period10
Referring to :
https://firebase.google.com/docs/database/web/lists-of-data#data-order
When using orderByKey() to sort your data, data is returned in ascending order by key.
Children with a key that can be parsed as a 32-bit integer come first, sorted in ascending order.
Children with a string value as their key come next, sorted lexicographically in ascending order.
You could avoid the "Period" as a redundancy as it is implied from the table and use the numeric id directly (not recommended by firebase) or use the push to generate the keys (ids) native to firebase.
The Firebase Database sorts strings lexicographically. And in alphabetical order Period10 comes before Period2.
To ensure the lexicographical order also matches the numerical order that you're looking for, you can consider padding the numbers:
Periods
+Period001
+Period010
+Period002
+Period003
+Period004
With this padding, the lexicographical order matches the numerical ordering that you're looking for. Of course the amount of padding will depend on the maximum number you realistically expect.
Alternatively you can simply store a Period property with a numeric value in each child node and order on that. In that case you can also use push IDs for the keys, as Alex said:
Periods: {
-Laaaaaa: {
Period: 1
},
-Laaaaab: {
Period: 10
},
-Laaaaac: {
Period: 2
},
-Laaaaad: {
Period: 3
},
-Laaaaae: {
Period: 4
}
}
Now you can query ref.orderByChild("Period") and the children will be returned in the wanted numerical order.

Mongoose field not required but unique [duplicate]

This question already has answers here:
mongoDB/mongoose: unique if not null
(4 answers)
Closed 5 years ago.
I have an email field set as unique, but it is not required.
The problem is that if the user does not enter anything Mongoose puts "null" in it. This causes duplicates because every user that does not enter the email field will have "null" assigned to it.
What is the standard practice to avoid this?
Thanks
Use a sparse unique index
If a document does not have a value for a field, the index entry for
that item will be null in any index that includes it. Thus, in many
situations you will want to combine the unique constraint with the
sparse option. Sparse indexes skip over any document that is missing
the indexed field, rather than storing null for the index entry.
db.collection.createIndex( { a: 1, b: 1 }, { unique: true, sparse: true } )
More information: https://docs.mongodb.com/v3.0/tutorial/create-a-unique-index/

Idempotency in MongoDB nested array, possible?

I am writing a REST api which I want to make idempotent. I am kind of struggling right now with nested arrays and idempotency. I want to update an item in product_notes array in one atomic operation. Is that possible in MongoDB? Or do I have to store arrays as objects instead (see my example at the end of this post)? Is it for example possible to mimic the upsert behaviour but for arrays?
{
username: "test01",
product_notes: [
{ product_id: ObjectID("123"), note: "My comment!" },
{ product_id: ObjectID("124"), note: "My other comment" } ]
}
If I want to update the note for an existing product_node I just use the update command and $set but what if the product_id isn't in the array yet. Then I would like to do an upsert but that (as far as I know) isn't part of the embedded document/array operators.
One way to solve this, and make it idempotent, would be to just add a new collection product_notes to relate between product_id and username.
This feels like violating the purpose of document-based databases.
Another solution:
{
username: "test01",
product_notes: {
"123": { product_id: ObjectID("123"), note: "My comment!" },
"124": { product_id: ObjectID("124"), note: "My other comment" } }
}
Anyone a bit more experienced than me who have anything to share regarding this?
My understanding of your requirement is that you would like to store unique product ids (array) for an user.
You could create an composite unique index on "username" and "username.product_id". So that when the same product id is inserted in the array, you would an exception which you could catch and handle in the code as you wanted the service to be Idempotent.
In terms of adding the new element to an array (i.e. product_notes), I have used Spring data in which you need to get the document by primary key (i.e. top level attribute - example "_id") and then add a new element to an array and update the document.
In terms of updating an attribute in existing array element:-
Again, get the document by primary key (i.e. top level attribute -
example "_id")
Find the correct product id occurrence by iterating the array data
Replace the "[]" with array occurrence
product_notes.[].note

Efficient Sorted Data Structure in JavaScript

I'm looking for a way to take a bunch of JSON objects and store them in a data structure that allows both fast lookup and also fast manipulation which might change the position in the structure for a particular object.
An example object:
{
name: 'Bill',
dob: '2014-05-17T15:31:00Z'
}
Given a sort by name ascending and dob descending, how would you go about storing the objects so that if I have a new object to insert, I know very quickly where in the data structure to place it so that the object's position is sorted against the other objects?
In terms of lookup, I need to be able to say, "Give me the object at index 12" and it pulls it quickly.
I can modify the objects to include data that would be helpful such as storing current index position etc in a property e.g. {_indexData: {someNumber: 23, someNeighbour: Object}} although I would prefer not to.
I have looked at b-trees and think this is likely to be the answer but was unsure how to implement using multiple sort arguments (name: ascending, dob: descending) unless I implemented two trees?
Does anyone have a good way to solve this?
First thing you need to do is store all the objects in an array. That'll be your best bet in terms of lookup considering you want "Give me the object at index 12", you can easily access that object like data[11]
Now coming towards storing and sorting them, consider you have the following array of those objects:
var data = [{
name: 'Bill',
dob: '2014-05-17T15:31:00Z'
},
{
name: 'John',
dob: '2013-06-17T15:31:00Z'
},
{
name: 'Alex',
dob: '2010-06-17T15:31:00Z'
}];
The following simple function (taken from here) will help you in sorting them based on their properties:
function sortResults(prop, asc) {
data = data.sort(function(a, b) {
if (asc) return (a[prop] > b[prop]);
else return (b[prop] > a[prop]);
});
}
First parameter is the property name on which you want to sort e.g. 'name' and second one is a boolean of ascending sort, if false, it will sort descendingly.
Next step, you need to call this function and give the desired values:
sortResults('name', true);
and Wola! Your array is now sorted ascendingly w.r.t names. Now you can access the objects like data[11], just like you wished to access them and they are sorted as well.
You can play around with the example HERE. If i missed anything or couldn't understand your problem properly, feel free to explain and i'll tweak my solution.
EDIT: Going through your question again, i think i missed that dynamically adding objects bit. With my solution, you'll have to call the sortResults function everytime you add an object which might get expensive.

Does JavaScript populate empty array items?

I am coding a lot of annual data in JavaScript, and I was considering adding it to arrays, using the year as the array index and putting the data into the array. However, Firebug seems to be indicating that JavaScript handles this by populating two thousand odd entries in the array with "undefined." With hundreds of such arrays kicking around in active memory, I'm worried the overhead of hundreds of thousands of useless array items could start to slow the program down. Will it?
When you set the value of a numeric index higher than the current length of your array, the length property is affected.
In brief, you should use an Object:
var data = {};
data[year] = "some data";
// or
var data = {
2009: "2009 data",
2010: "2010 data"
};
Now I answer the question title: "Does JavaScript populate empty array items?"
No, as I said before, only the length property is changed, (if necessary, only if the index added is larger than the current length), length is incremented to be one more than the numeric value of that index.
The Array.prototype methods work assuming that the array object will have its indexes starting from zero.
The previous indexes don't really exist in the Array object, you can test it:
var array = [];
array[10] = undefined;
array.hasOwnProperty(10); // true
array.hasOwnProperty(9); // false
In conclusion, arrays are meant to contain sequential indexes, starting from zero, if your properties don't meet those requirements, you should simply use an object.
Yes, most likely. You should consider using a JavaScript object instead:
var years = {2009: 'Good', 2010: 'Better'};
Well, if you iterate over many thousands of undefined, it will affect overall program speed, not sure if you'll notice it though.
On the other hand, sometimes a sparse array is simpler to use than a custom object,
and arrays have such handy methods available.
In a calendar application I begin with objects for each year in use, but each year consists of a twelve member (months array) and each 'month' is a sparse array of significant dates, whose lengths depend on the highest date of that month that has any data.

Categories