How to find an id in an array in mongoose using nodejs - node.js

I have data something like below:
{
"_id": "60708607143b058e101fc189",
"orders": {
"userID": "606eaa5cf67ac70cfa347fcd",
"order": [
{
"productIDs": [ "606f1f37006513258c8b59b9" ],
"vendorID": "60641cf597aed2a9a2971a3f",
"id": "60708607143b058e101fc18a"
},
{
"productIDs": [ "606f1fec006513258c8b59ba", "606f2bb2006513258c8b59bd" ],
"vendorID": "60642991015028ba0a6ce72c",
"id": "60708607143b058e101fc18b"
}
]
},
}
Is there a way to find any given vendorID in this record using nodejs and mongoose?

If you are logged in as a vendor, then you can send the vendor_id in the body of the request. To filter all orders associated to that particular vendor, you can try this:
Model.find({"orders.order":
{
"$elemMatch": {
"vendorID": req.body.vendor_id
}
}
});

Related

Using cond in mongo aggregate match expression

So i'm trying to query products based on the user specified filter. if the user specifies the size, for example XS, then i fetch all the products with 'XS' sizes, otherwise if the size isn't specified then i will fetch all the products without checking for their size. How can i do it with the mongo aggregation ?
here's my code.
1st: here's 2 products documents from my collection
[
{
"_id": "6124d16b1396d20aea617d75",
"username": "josh988",
"userpic": "josh.jpg",
"adresse": "545 Strawberry Lane Mokena, IL 60448",
"city": "Paris",
"country": "France",
"product": {
"_id": "62c064103a7b5160e957764c",
"images": [
"img1734116er1111111.jpeg"
],
"name": "White shirt",
"category": "Kids",
"subCategory": "Tshirts",
"size": "XS",
"price": 150
}
},
{
"_id": "6124d16b1396d20aea617d75",
"username": "laurel22",
"userpic": "laurel.jpg",
"adresse": "545 Strawberry Lane Mokena, IL 60448",
"city": "Lyon",
"country": "France",
"product": {
"_id": "62c064103a7b5160e957764c",
"images": [
"img1711656775696063.jpeg"
],
"name": "Black shirt",
"category": "Kids",
"subCategory": "Tshirts",
"size": "M",
"price": 250
}
},
]
to make the matter simple , my body api body request looks like this
{
"selectedCategory": "Kids",
"selectedSubCategory": "Tshirts",
// for e.g selectedSize could be XS
"selectedSize": null
}
So what i'd like to do is, if the user select a size then fetch the products with it otherwise fetch everything.
I tried this with mongo but didn't work
const searchResults = await user.aggregate([
{
$match: {
"product.category": `${req.body.selectedCategory}`,
"product.subCategory": `${req.body.selectedSubCategory}`,
$expr: {
$cond: {
// what should i do here ? or is there another way of achieving this
if: { $ne: [`${req.body.selectedSize}`, null] },
then: { product.size : req.body.selectedSize },
// and what should write here to fetch everything
else: { product.size: "" },
},
},
},
},
]);
You can generate the aggregation pipeline conditionally in nodejs itself. Like this:
let matchStage = {
$match: {
"product.category": `${req.body.selectedCategory}`,
"product.subCategory": `${req.body.selectedSubCategory}`,
}
};
if(req.body.selectedSize) {
matchStage = {
$match: {
...matchStage["$match"],
"product.size": request.body.selectedSize
}
};
}
const searchResults = await user.aggregate([matchStage]);

Mongoose find and return only a part of the document

My object:
[
{
"_id": "568ad3db59b494d4284ac191",
"name": "Test",
"groups": [
{
"number": "1",
"name": "GroupTest",
"_id": "568ad3db59b494d4284ac19b",
"orders": [
{
"date": "2016-03-06T13:07:40.990Z",
"_id": "56dc2b9c1d47772806e4f0f4",
"readings": [
{
"readingid": "568ad3db59b494d4284ac1a5",
"_id": "56dc2b9c1d47772806e4f0fc"
},
{
"readingid": "568ad3db59b494d4284ac1a4",
"_id": "56dc2b9c1d47772806e4f0fb"
},
{
"readingid": "568ad3db59b494d4284ac1a3",
"_id": "56dc2b9c1d47772806e4f0fa"
},
{
"readingid": "568ad3db59b494d4284ac1a2",
"_id": "56dc2b9c1d47772806e4f0f9"
},
{
"readingid": "56d48ae1a0f6e04413fc8b3e",
"_id": "56dc2b9c1d47772806e4f0f8"
},
{
"readingid": "56d48ae1a0f6e04413fc8b3f",
"_id": "56dc2b9c1d47772806e4f0f7"
},
{
"readingid": "568ad3db59b494d4284ac1a1",
"_id": "56dc2b9c1d47772806e4f0f6"
},
{
"readingid": "568ad3db59b494d4284ac1a0",
"_id": "56dc2b9c1d47772806e4f0f5"
}
]
},
{....}
]
},
{....}
]
},
{.....}
]
I need to finde the order with the _id: "56dc2b9c1d47772806e4f0f4" in the group with the _id: "568ad3db59b494d4284ac19b" inside the client object with _id:"568ad3db59b494d4284ac191" and I only want to get that order subobject, not the whole client object.
I tried something like:
Client.find(
{_id: "568ad3db59b494d4284ac191", groups._id: "568ad3db59b494d4284ac19b", groups.orders._id:"56dc2b9c1d47772806e4f0f4"},
{groups.orders:{$elemMatch:{_id: "56dc2b9c1d47772806e4f0f4"}}})
Antoher attempt without success:
Client.find(
{_id: req.company, groups:ObjectId(req.params.groupId)},
{"groups.orders":{$elemMatch:{_id: ObjectId(req.params.orderId)}}}, function(e,company){
if(!e) {
console.log(company);
}
});
mongo is a "document-oriented" database, so all the normal operations and queries it provides return "documents" and not "parts of documents", so with the normal query methods there is no way to get just a subobject.
You can use the mongo aggregation framework to achieve what you want (https://docs.mongodb.org/manual/reference/operator/aggregation/), using two $unwind: https://docs.mongodb.org/manual/reference/operator/aggregation/unwind/ .
This will produce a document for each order and then use $match to filter out the ones you need.
But probably it might be better to rethink your data model. If you really need to query and retrieve orders only, without getting the whole client object, it might be better to store the orders in their own collection and use references to groups and clients.

How to get filtered result by using Hash Index in ArangoDB?

My data:
{
"rootElement": {
"names": {
"name": [
"Haseb",
"Anil",
"Ajinkya",
{
"city": "mumbai",
"state": "maharashtra",
"job": {
"second": "bosch",
"first": "infosys"
}
}
]
},
"places": {
"place": {
"origin": "INDIA",
"current": "GERMANY"
}
}
}
}
I created a hash index on job field with the API:
http://localhost:8529/_db/_api/index?collection=Metadata
{
"type": "hash",
"fields": [
"rootElement.names.name[*].jobs"
]
}
And I make the search query with the API:
http://localhost:8529/_db/_api/simple/by-example
{
"collection": "Metadata",
"example": {
"rootElement.names.name[*].jobs ": "bosch"
}
}
Ideally, only the document containing job : bosch should be returned as a result. But for me it gives all the documents in the array name[*]. Where I am doing mistake?
Array asterisk operators are not supported by simple queries.
You need to use AQL for this:
FOR elem IN Metadata FILTER elem.rootElement.names.name[*].jobs = "bosch" RETURN elem
You can also execute AQL via the REST interface - However you should rather try to let a driver do the heavy lifting for you.

cloudant searching index by multiple values

Cloudant is returning error message:
{"error":"invalid_key","reason":"Invalid key use-index for this request."}
whenever I try to query against an index with the combination operator, "$or".
A sample of what my documents look like is:
{
"_id": "28f240f1bcc2fbd9e1e5174af6905349",
"_rev": "1-fb9a9150acbecd105f1616aff88c26a8",
"type": "Feature",
"properties": {
"PageName": "A8",
"PageNumber": 1,
"Lat": 43.051523,
"Long": -71.498852
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-71.49978935969642,
43.0508382914137
],
[
-71.49978564033566,
43.052210148524
],
[
-71.49791499857444,
43.05220740550381
],
[
-71.49791875962663,
43.05083554852429
],
[
-71.49978935969642,
43.0508382914137
]
]
]
}
}
The index that I created is for field "properties.PageName", which works fine when I'm just querying for one document, but as soon as I try for multiple ones, I would receive the error response as quoted in the beginning.
If it helps any, here is the call:
POST https://xyz.cloudant.com/db/_find
request body:
{
"selector": {
"$or": [
{ "properties.PageName": "A8" },
{ "properties.PageName": "M30" },
{ "properties.PageName": "AH30" }
]
},
"use-index": "pagename-index"
}
In order to perform an $or query you need to create a text (full text) index, rather than a json index. For example, I just created the following index:
{
"index": {
"fields": [
{"name": "properties.PageName", "type": "string"}
]
},
"type": "text"
}
I was then be able to perform the following query:
{
"selector": {
"$or": [
{ "properties.PageName": "A8" },
{ "properties.PageName": "M30" },
{ "properties.PageName": "AH30" }
]
}
}

How to combine multiple CouchDB queries into a single request?

I'm trying to query documents in a Cloudant.com database (CouchDB). The two following query requests work fine separately:
{ "selector": { "some_field": "value_1" } }
{ "selector": { "some_field": "value_2" } }
Cloudant's documentation seems to indicate I should be able to combine those two queries into a single HTTP request as follows:
{ "selector": { "$or": [ { "some_field": "value_1" },
{ "some_field": "value_2" } ] } }
But when I try that I receive the following response:
{"error":"no_usable_index",
"reason":"There is no operator in this selector can used with an index."}
Can someone tell me what I need to do to get this to work?
There doesn't seem to be a way to achieve this with Cloudant Query at the moment. However, you can use a view query instead using the index created with Cloudant Query. Assuming the index is in a design document named ae97413b0892b3738572e05b2101cdd303701bb8:
curl -X POST \
'https://youraccount.cloudant.com/db/_design/ae97413b0892b3738572e05b2101cdd303701bb8/_view/ae97413b0892b3738572e05b2101cdd303701bb8?reduce=false&include_docs=true' \
-d '
{
"keys":[
["value_1"],
["value_2"]
]
}'
This will give you a response like this:
{
"total_rows": 3,
"offset": 1,
"rows": [
{
"id": "5fcec42ba5cad4fb48a676400dc8f127",
"key": [
"abc"
],
"value": null,
"doc": {
"_id": "5fcec42ba5cad4fb48a676400dc8f127",
"_rev": "1-0042bf88a7d830e9fdb0326ae957e3bc",
"some_field": "value_1"
}
},
{
"id": "955606432c9d3aaa48cab0c34dc2a9c8",
"key": [
"ghi"
],
"value": null,
"doc": {
"_id": "955606432c9d3aaa48cab0c34dc2a9c8",
"_rev": "1-68fac0c180923a2bf133132301b1c15e",
"some_field": "value_2"
}
}
]
}

Resources