MongoDB query with condition on multiple records - mongodb

This might be trivial, but I haven't figured out a way to do it.
Say I have the following records in the database:
{ A: 1, B: 2, C: "Red" }
{ A: 1, B: 2, C: "Blue"}
{ A: 1, B: 3, C: "Red" }
And I want to return all records with {A: 1, C: "Red"}, but not when C: "Blue" if there are multiple records with the same B values. So for the above records, it'll only return the 3rd record. The 1st record would not be returned because there are two records with the same B value, and one of them has C: "Blue" as a value.
I can only think of doing this via two queries to the database, i.e. first query {A:1, C:"Red"}, then check by querying all elements in database. I suppose the second step might actually be many more than just 1 query.
I don't really want to query with {A: 1}. Of course, I'm doing all this through the API, so this way it'll be one database query, but the resulting list could be much bigger than I'd like.
Is there a query that can do what I want via just 1 database call? Thanks.

I don't think it's possible with one query. But you can get all B you want with aggregate and then query database for that B:
db.test1.aggregate(
[
{$group: {_id: "$B", count: {$sum:1}}},
{$match: {count:1}}
]
)
will return you all B for which there only one record in your collection.

Related

How to create index for the following kind of data in mongodb

db.test.insert({a:1, b:[1])
db.test.insert({a:1, b: 1})
db.test.insert({a:[1], b: 1})
db.test.insert({a:[1], b: [1]})
what should be a right way to index the fields so that i can query over a and b?
{ _id: 1, a: [1, 2], b: 1, category: "A array" }
{ _id: 2, a: 1, b: [1, 2], category: "B array" }
A compound multikey index { a: 1, b: 1 } is permissible since for each
document, only one field indexed by the compound multikey index is an
array; i.e. no document contains array values for both a and b fields.
However, after creating the compound multikey index, if you attempt to
insert a document where both a and b fields are arrays, MongoDB will
fail the insert.
---- Documentation
But one of your doc's a & b both contain array.

What's the best Mongo index strategy that includes a date range

I have the following schema:
{
a: string;
b: date;
c: number;
}
My query is
find({
a: 'some value',
b: {
$gte: new Date('some date')
}
})
.sort({
c: -1
});
I have an index that is:
{ a: 1, b: 1, c: 1 }
But it's not using this index.
I have several other indexes, and when analyzing my explain(), it shows it's employing multiple other indexes to accomplish my query.
I believe since my "b" query is a date range, that's not considered an equality condition, so maybe that index won't work?
Should I have two indexes:
{ a: 1, c: 1} and separately { b: 1 }
Dates tend to be much more selective than other fields, so when you have an index that looks like {dateField: 1, otherField: 1}, the selectivity of the dateField means that otherField will be useless unless you have multiple items that share the same date.
Depending on what your data distribution actually looks like, you might consider {otherField: 1, dateField: 1} (which means that mongo can go through in sorted order to check whether the docs match your date query). In general, putting your sort field before any fields used in a range query is a good idea.
Mlab's indexing docs are the best resource I've seen on index usage, and they recommend:
A good rule of thumb for queries with sort is to order the indexed fields in this order:
First, the field(s) on which you will query for exact values
Second, one small $in array
Third, the field(s) on which you will sort in the same order and specification as the sort itself (sorting on multiple fields)
Finally, the field(s) on which you will query for a range of values in the order of most selective to least selective (see range operators below)

What are the tradeoffs of creating a new compound index versus adding to an existing?

I'm querying by fields a,b, and c, and have this index:
{a: 1, b: 1, c: 1}
I'm adding a new query on a, sorted by d desc. Should I change the index to:
{a: 1, b: 1, c: 1, d: -1}
Or should I add a second index:
{a: 1, d: -1}
In this case, changing the index doesn't work (see http://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/#sort-and-non-prefix-subset-of-an-index).
In the general case of querying non-sequential compound index fields, while creating indexes always takes up more memory, it will perform better:
"However, the index would not be as efficient in supporting the query as would be an index on only item and stock."
http://docs.mongodb.org/manual/core/index-compound/

Mongodb - Query MultiKey Indexed Documents

My question is about the way MongoDB operates when querying MultiKey document.
Assuming I have these documents:
{
a: 1,
b: 2,
c: ['x','y','z']
},
{
a:3,
b: null,
c: ['x','z']
}
My query is this:
db.<collection>.find({ b: null, c: 'x'})
And my index is:
db.<collection>.ensureIndex({ c: 1 })
My question is: For the query above (that asks for c AND b), how does MongoDB invokes the query? Does it 'see' that I have an index on c or does it try to only look for an index for both c AND b ?
Thanks Disposer
The query just finds the index of c even if the statement includes c and b.

MongoDB Covered Query For Two Fields Without Compound Index

Can you perform a MongoDB covered query for two fields, for example
db.collection.find( { _id: 1, a: 2 } )
without having a compound index such as
db.collection.ensureIndex( { _id: 1, a: 1 } )
but instead having only one index for _id (you get that by default) and another index for field "a", as in
db.collection.ensureIndex( { a: 1 } )
In other words, I'd like to know if in order to perform a covered query for two fields I need a compound index vs. needing only two single (i.e., not compound) indexes, one for each field.
Queries only use one index.
Your example shows _id as one of the elements of your index? _id Needs to be unique in a collection, so it wouldn't make sense to make a compound index of _id and something else.
If you instead had:
db.collection.ensureIndex( { a: 1, b: 1 })
You could then use the a index as needed, independently, or as a compound index with b.