[SERVER-2363] $push/$pushAll support for insertion at any position (top/bottom/ordinal) Created: 15/Jan/11  Updated: 08/Feb/19  Resolved: 11/Oct/13

Status: Closed
Project: Core Server
Component/s: Write Ops
Affects Version/s: None
Fix Version/s: 2.5.3

Type: Improvement Priority: Minor - P4
Reporter: Scott Hernandez (Inactive) Assignee: Scott Hernandez (Inactive)
Resolution: Done Votes: 8
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
depends on SERVER-2362 Add new Deque/Set operation modifiers Closed
depends on SERVER-6399 Refactor update() code Closed
Duplicate
is duplicated by SERVER-1824 Support for inserting into specific a... Closed
is duplicated by SERVER-2191 $push() to front of array Closed
is duplicated by SERVER-6873 Inserting a unique value into a speci... Closed
Related
related to SERVER-991 $push with $slice + $sort Closed
related to SERVER-2036 $insert and $remove for arrays (curre... Closed
is related to SERVER-13521 Allow fast $push to front of an array Backlog
is related to SERVER-39446 $push/$pushAll to honor $position pas... Closed
Participants:

 Description   

Add $position option which takes a positive number.

db.col.save({_id:1, a: [3]})
db.col.update({}, {$push: {a: {$each:[1,2], $position:0 }}}) // pushes to front of array

If $position is equal to or greater than the array size then it will be ignored and is effectively a push to the end, which is the default behavior if not specified.

This will allow you to effectively $pop from the top and add to the bottom or vice versa using $slice since you push in either direction.



 Comments   
Comment by auto [ 11/Oct/13 ]

Author:

{u'username': u'scotthernandez', u'name': u'Scott Hernandez', u'email': u'scotthernandez@gmail.com'}

Message: SERVER-2363 $push support for insertion at any position
Branch: master
https://github.com/mongodb/mongo/commit/967dbe1b27ac6459c15d02c30dd6a0790203d54e

Comment by Jan Riechers [ 31/Aug/12 ]

Artem, I just added my vote, but perhaps it's also a good idea to push this ticket info (with short summary onto the mailinglist?) to get attention to it. Also my proposal differs somehow from the initial post and it might be kinda misleading to what is beeing voted for.

I personally don't agree with shift/unshift in total, for me it takes more understanding, from a stack/array logic point of view, to understand those and I see those in a broader concept: (not onlty top/bottom)

Idea for me:
"$shift" -> shifts any item in question by the stack by (possible negative value for updwards) X positions from current position, either finding it by direct addressing it as 'Item2', or by positional index - if the position is out of reach, the item just drops to the end of the list.

But this way of course assumes, that you exactly know the position of the element to be moved, and this can of course change if the current information is outdated and there are no reference counters (probably a bad idea, I dunno).
On the other hand, if one wants a dynamic increasing stack (forwards and backwards) - shifting with "null" value inserts could also be desired, but perhaps sometimes not of course..

Thats why I came up with the examples
$pushAt, $popFrom, $pullOnce - cause one can

in heavy updated documents:
$pushAt" -> Pushes at exact positon, $pullOnce - removes one existing, but unique, value from the stack/array

But of course, keeping track of an object position - for example by referencing a index position is kinda risky - assuming anohter element gets pushed at the same position - but we don't track the previous item has moved one forward (down) in the array. But this might also depend on the use case and $pullOnce may come into play.

in single documents not affected by massive changes:
"$popFrom" -> If we we are safe with a document, we tell mongo exactly which position to be removed,
of course also the "$pullOnce" solution can be used, but this involves scanning data - which might be not neccesary - but I agree that this command is quite special as most of the time one not might know beforehand the actual positon of one item so.

Anyhow, sorry for this long post so, but I hope it makes sense.

Comment by Artem [ 30/Aug/12 ]

Jan +1 I want $pushAt and $popFrom too. Have you voted for this issue? We need to get more votes to move this issue from "planned but not scheduled" to "Planning Bucket A"

Comment by Jan Riechers [ 27/Aug/12 ]

Hello,

would it be possible to integrate a $pushAt, $popFrom queries, meaning:
$pushAt - pushes an item to a specific position (most likely an array)
$popFrom - removes an item from a given position
both methods should require of course a position operator - most likely an array?

At the moment "$pull" removes/searches for many values inside an array, but if there is only one (surely) item to be removed, perhaps it would be more performant to have something like
"$pullOne" or similiar and then exit the operation without touching any subsequent items of an array to increase performance in difference to ordinary "$pull" (seeking through all elements)

Is this possible?

Comment by Aaron Heckmann [ 28/Jan/12 ]

Agree with $push/$pop/$unshift/$shift semantics being intuitive.

Comment by Eliot Horowitz (Inactive) [ 16/Jan/11 ]

Not sure if both will happen or one, but marked as related .

Comment by Keith Branton [ 16/Jan/11 ]

@Scott - I'm not aware of any other uses for push in programming besides stacks. In stack semantics "push" means "add item to top of stack". The current $push operation is consistent with this. The deque is the data structure that supports adding and removing at both ends. The most common names for deque operations in modern languages are $push/$pop/$unshift/$shift. These are at least common to javascript, ruby, PHP (with array_ prefix) and perl. Since Mongo already uses $push and $pop, it makes sense to keep the operations at the other end of the structure consistent with the languages that use push and pop.

Since $push adds an item to the end of an array, it seems that the end of the array is the top, and the front must, therefore, be the bottom. So $pushToTop would be a very misleading name for an operation that adds an item to the bottom.

I believe good naming, consistent with common CS concepts, is much more intuitive and lowers the barrier to entry for newbies, but honestly I'm not so concerned with what the modifiers ultimately get called I'm not really a big fan of the names $shift and $unshift either - but I am a very big fan of consistency.

Comment by Scott Hernandez (Inactive) [ 15/Jan/11 ]

This issue is independent of your issue/proposal; I am not making the assumption that what your propose will every come to be, or is even good. I'm just asking for improvements to the current features.

There are many ways to keep backwards compatibility. We can add $pushToTop to the update, or to the $push document.

(I don't like $(un)shift*; it is not intuitive. $push with a modifier for direction seems very simple, and works, rather than a new operator/modifier.)

Comment by Keith Branton [ 15/Jan/11 ]

This duplicates much of my ticket: http://jira.mongodb.org/browse/SERVER-2362

I already requested $unshift with $each support on that ticket which would take care of $push and $pushAll insertion at top. -1 for changing $pushAll at all - it should be deprecated in favor of $push with $each, not enhanced.

Since $push looks like { $push :

{ field : value }

} it's hard to see how that could be changed to support insertion in the top while maintaining backwards compatibility in an elegant way or semantic correctness.

I'm not sure I understand the benefit of this proposal wrt $addToSet. Is there a use-case that the current $addToSet, and proposed $pushToSet and $unshiftToSet modifiers wouldn't satisfy? I have documented a couple on 2363 that this proposal would certainly not satisfy.

Generated at Thu Feb 08 02:59:44 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.