Check which elements of an array belong to a collection without using loop? - mongodb

I have a collection of 10000 items in MongoDB. The front end user submits an array of 100 items, and wants to know which of the 100 items belong to my collection.
Can I query it without using a loop?
Thanks!
----update: "more details" requested by comment:----
Sure, let's suppose my collection is about books (_id, book title, author name). Front end user submits an array of book titles. I need to answer which of the titles can be found in the db.
Also, suppose the book titles are always unique on both ends.

you can just use the $in operator which expects an array with titles of books and it should return the objects which contain the same.
db.getCollection('book').find({ title: { $in: ["string1", "string2"] }})

Related

How to query a firestore array with multiple key value pairs in Swift

One of my collections in Cloud Firestore has an where each item in the array contains three separate values (see the groupMembership field:
I know I can't write a query to find documents that match one of the array values. Is there a way to write a query to find documents that match a specific value for all three items?
For instance, I want to find all users where the groupMembership array contains one object that is equal to groupId: X, groupName: Y, membershipStatus: active
You can pass the entire object in an array-contains clause.
So something like:
usersRef
.whereField("groupMembership", arrayContains: [
"groupId": "kmDT8OUOTCxSMIBf9yZC",
"groupName": "Jon and Charles Group",
"membershipStatus": "pending",
])
The array item must completely and exactly match the dictionary you pass in. If you want to filter only on some of the properties in each array element, you will have to create additional fields with just those properties. For example, it is quite common to have say a field groupIds with just the (unique) group Ids, so that you can also filter on those (of course within the limits of Firestore's queries).

How to query a FireStore datamodel with 2 related collections for only documents if a field exists in another collection

I have 2 collection:
categories
id:
name:
books
id:
name:
categories: []
a book has an title and an array of the categories it belongs to.
I want make a query to show only all the categories if there a related book.
Otherwise a user sees category 'x' and when going to then next screen, there are 0 related books. This i don't want, so category 'x' should not be in the list of all the avaiable categories on that screen.
How to do that? Is my datamodel the right one?
Thanks inadvance for the answers ;)
In relational DBs this would be done with a Join but the issue is that Firestore doesn't have joins.
So this query will need to be performed manually by getting all the books, concatenating categories arrays and then removing repeated values.

mongodb - one document in many collections

I'am looking for a good solution on MongoDB for this problem:
There are some Category's and every Category has X items.
But some items can be in in "many" Category's!
I was looking for something like a symbolic link on Unix systems but I could't not find it.
What i thought is a good idea is:
"Category1/item1" is the Object and "category2/item44232" is only a reference to "item1" so when i change "item1" it also changes "item44232".
I looked into the MongoDB Data models documentation but there is no real solution for this.
Thank you for your response !
In RDBMSs, you use a join table to represent one-to-many relationships; in MongoDB, you use array keys. For example each product contains an array of category IDs, and both products and categories get their own collections. If you have two simple category documents
{ _id: ObjectId("4d6574baa6b804ea563c132a"),
title: "Epiphytes"
}
{ _id: ObjectId("4d6574baa6b804ea563c459d"),
title: "Greenhouse flowers"
}
then a product belonging to both categories will look like this:
{ _id: ObjectId("4d6574baa6b804ea563ca982"),
name: "Dragon Orchid",
category_ids: [ ObjectId("4d6574baa6b804ea563c132a"),
ObjectId("4d6574baa6b804ea563c459d") ]
}
for more: http://docs.mongodb.org/manual/reference/database-references/
Try looking at the problem inside-out: Instead of having items inside categories, have the items list the categories they belong into.
You'll be able to easily find all items that belong to a category (or even multiple categories), and there is no duplication nor any need to keep many instances of the same item updated.
This can be very fast and efficient, especially if you index the list of categories. Check out multikey indexes.

In Mongodb, how to retrieve the subset of an object that matches a condition?

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

How to annotate the result documents with a count of child documents?

I have a collection of categories, each category document containing a link to its parent (except the root categories). Pretty simple so far.
I want to list the categories, and add a subcategory_count field to every document with the count of direct descendants.
How should I go about doing this? Could Map/Reduce be of use?
There are no "calculated columns" in MongoDB, so you can't select data and count subdocuments at the same time.
This is also the reason why most people store array length along with the array.
{friends_list: [1, 3, 234, 555],
friends_count: 4}
This helps for easier retrieval, filtering, sorting, etc. But it requires a little bit more of manual work.
So, you are basically limited to these options:
Store everything in one document.
Store subcategory count in the category.
Count subcategories on the client-side.
find() to get all of them, count the number of subcategories on each level and then update().
But it seems like your domain object should be doing this for you, so you end up with one category object that can contain categories (which could also contain categories...), and hence one mongodb document (you're listing all of them anyway, so it makes sense to retrive the whole thing in one query).