I had a collection with an embedMany attribute using strategy=set, so an ArrayCollection was stored. However we deleted some items from the array and now there are some documents with keys not sequential integers.
I need to solve this inconsistence, how can I do that?
You could use $type operator and query for all documents where your embedManyField is of type object. Once you have these documents, apply array_values to fields where array shall be stored and save them again. Also to avoid such situations in future you should change your collection's strategy to either setArray or atomicSetArray.
http://docs.mongodb.org/manual/reference/operator/aggregation/match/
The documentation says absolutely nothing about what type of object is returned.
I know however from testing that it returns an array if I get multiple documents back.
Must I use $limit if I only want to get back one document even though $match only matches one document (it seems to return an array in any case)?
This is my meteor code to search whether user exist in the array or not
var u_exist=Polls_Coll.findOne( {option1:{$elemMatch:{ids:"xxx"}}} );
My question is, How to know whether the statement returning something or not(user exist or not)
$elemMatch will return only where one of the conditions supplied actually finds a match in the array. So if you don't get a document back then there was no match.
Also findOne is a single document. Modifiers such as .count() will not work on that. If you have more documents to be expected use find intstead. Also findOne not not make much sense without applying a unique identifier such as _id in the query. Without that you are almost certainly not getting what you want.
While useful for your purpose, findOne is not a good match with the $elemMatch operator. The reasoning is you can possibly get multiple results of the same document having the same set of array elements that matched the condition that you gave.
Buyer beware.
What I'm trying to do:
Filter a field of a collection that matches a given condition. Instead of returning every item in the field (which is an array of items), I only want to see matched items.
Similar to
select items from test where items.histPrices=[10,12]
It is also similar to what's found on the mongodb website here: http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields
Here's what I have been trying:
db.test.save({"name":"record", "items":[{"histPrices":[10,12],"name":"stuff"}]})
db.test.save({"name":"record", "items":[{"histPrices":[10,12],"name":"stuff"},
{"histPrices":[12,13],"name":"stuff"},{"histPrices":[11,14],"name":"stuff"}]})
db.test.find({},{"name":1,"items.histPrices":[10, 12]})
It will return all the objects that have a match for items.histPrices:[10,12], including ALL of the items in items[]. But I don't want the ones that don't match the condition.
From the comments left on Mongodb two years ago, the solution to get only the items with that histPrices[10,12] is to do it with javascript code, namely, loop through the result set and filter out the other items.
I wonder if there's a way to do that with just the query.
Your find query is wrong
db.test.find({},{"name":1,"items.histPrices":[10, 12]})
Your condition statement should be in the first part of the find statement.In your query {} means fetch all documents similar to this sql
select items from test (no where clause)
you have to change your mongodb find to
db.test.find({"items.histPrices":[10, 12]},{"name":1})
make it work
since your items is an array and if you wanted to return only the matching sub item, you have to use positional operator
db.test.find({"items.histPrices":[10, 12]},{"name":1,'items.$':1})
When working with arrays Embedded to the Document, the best approach is the one suggested by Chien-Wei Huang.
I would just add another aggregation, with the $group (in cases the document is very long, you may not want to retrieve all its content, only the array elements) Operator.
Now the command would look like:
db.test.aggregate({$match:{name:"record"}},
{$unwind:"$items"},
{$match {"items.histPrices":[10, 12]}},
{$group: {_id: "$_id",items: {$push: "$items"}}});)
If you are interested to return only one element from the array in each collection, then you should use projection instead
The same kind of issue solved here:
MongoDB Retrieve a subset of an array in a collection by specifying two fields which should match
db.test.aggregate({$unwind:"$items"}, {$match:{"items.histPrices":[10, 12]}})
But I don't know whether the performance would be OK. You have to verify it with your data.
The usage of $unwind
If you want add some filter condition like name="record", just add another $march at first, ex:
db.test.aggregate({$match:{name:"record"}}, {$unwind:"$items"}, {$match:{"items.histPrices":[10, 12]}})
https://jira.mongodb.org/browse/SERVER-828
Get particular element from mongoDB array
MongoDB query to retrieve one array value by a value in the array
I am using MongoDB with node.js. Is it possible to persist data as an (unordered) set in MongoDB directly? Or do I have to either
persist them as an array and transform it into a set in JavaScript
or
persist them as an object in the form of {entry1: true, entry2: true, ...}
If I have to do it in either of the two ways above, which one is more efficient? Considering I need to add/remove items frequently, but rarely need to re-assign the whole set/array.
You can manipulate an array as a set in MongoDB... relevant operators include:
$addToSet - The $addToSet operator adds a value to an array only if the value is not in the array already.
$push - The $push operator appends a specified value to an array.
$pop - The $pop operator removes the first or last element of an array.
$pull - The $pull operator removes all instances of a value from an existing array.
$elemMatch - The $elemMatch operator matches more than one component within an array element.