I have the following Schema set up on mongoose
{
_id:
store:
offers:[{
name:
price:
}]
}
I decided to indexed offers.name as follows
uniSchema.index({'offers.name':'text'});
and now I'm trying to do searches on that index
Stores.find({$text:{$search:VALUE}}, callback);
But this way whenever there's a hit on the search the whole store is listed, and I'm unable to figure out from which offer the match came from.
Is there a way to do this with indexes on mongoose? Figuring out which array element matched the query?
I'm not sure that's possible with a $text index.
With a straight query you can use a projection to do the same:
> db.array_find.find({ "offers.name": "firstname"},{"offers.$" : 1} )
But the text query doesn't reference the array directly so offers.name is not able to be used in the projection.
> db.array_find.find({ $text: { $search: "firstname"} },{"offers.$" : 1} )
error: {
"$err" : "Can't canonicalize query: BadValue Positional projection 'offer.$' does not match the query document.",
"code" : 17287
}
The problem with attempting any type of post processing of the array from a result document is your not going to be using mongo's text indexing but some approximation of it.
You may need a different data structure
_id:
store: 2
offer:
name: this is a single offer
price: 4
_id:
store: 2
offer:
name: this is the next offer
price: 5
Related
I want to search if a keyword present in any of the fields in documents. some field values are objects.so it is also needed to check whether the keyword present inside that object also.
so I came across the following solution.
collections: products(having companyId as foreign key), company
mongoQuery
db.products.aggregate([{$match:{$text:{$search:"hello"}}},{$lookup:{from:"companies",localField:"companyId",foreignField:"_id",as:"company"}},{$unwind:"$company"}])
result
`
[
{
_id: ObjectId("63832de4e9dbcd9b2942ded7"),
companyId: [ ObjectId("6383048ae9dbcd9b2942dece") ],
title: 'hello world',
imageUrl: 'https://drive.google.com/file/image',
company: {
_id: ObjectId("6383048ae9dbcd9b2942dece"),
name: 'name1',
url: 'name1.com'
}
}
]
`
But problem is that i have another document where 'company.name' having value "hello".By using above query it doesn't return the second document.How can i solve this problem?
$or is your correct approach: https://www.mongodb.com/docs/manual/reference/operator/query/or/
Just use it with .find as example links shows and you will get an array of documents.
I'm using ArangoDB version 3.9, I have a document-based collection named myCollection2. Each document in this collection has a 'likes' attribute, which is holding a float numeric value. Documents are dummy data now, where I used the following query to create it.
FOR i IN 1..998700000
INSERT {
title: RANDOM_TOKEN(32),
description: RANDOM_TOKEN(32),
by: RANDOM_TOKEN(32),
url: CONCAT(CONCAT("http://www.",RANDOM_TOKEN(32)),".com"),
tags: [RANDOM_TOKEN(10), RANDOM_TOKEN(10), RANDOM_TOKEN(10)],
likes: FLOOR(RAND() * (51)),
comments: [
{
user:RANDOM_TOKEN(24),
message: RANDOM_TOKEN(100),
dateCreated: DATE_ISO8601(946681801000 + FLOOR(RAND() * 1000000000000)),
likes: FLOOR(RAND() * (51))
}
]
} IN myCollection2
Then I added a persistent index to the collection on the likes attribute and used the query below to find documents with some value.
FOR s in myCollection2
FILTER s.likes == 29.130405590990936
return s
knowing that the value 29.130405590990936 actually exists in some documents, the above query is taking about ~8 ms, which is great. However, when using some other value that doesn't actually exist, say for example 10, the query takes almost about 1 hour, which is crazy. Am I missing something here?
An update in the array of objects inside another array of objects.
mongodb field that I'm working on:
otherFields: values,
tasks: [
{
_id: mongodb.objectID(),
title: string,
items:[{
_id: mongodb.objectID(),
title: string,
completed: boolean //field need to be update.
}]
},
{}...
],
otherFields: value
sample mongodb document
I need to find the document using the task_id and the item_id and update a completed field in item of a task. Using the mongoose findOneAndUpdate method
const path = "tasks.$.items." + item_id + "completed";
collectionName.findOneAndUpdate(
{ _id: req.user._id, "tasks._id": taskID },
{ $set: { [path]: true }});
The above query doesn't work!!!
There is no need to use multiple query conditions, since you'd like to update a specific item that has an unique ID. Therefore you could use something along the lines:
collectionName.findOneAndUpdate(
{ 'tasks.items._id': itemID },
...
);
Keep in mind this structure is far away from optimized as it would basically look through the entire database...
Also now that I think of it, you'd also have issue with the update, as there are two nested arrays within the document. Read more here: How to Update Multiple Array Elements in mongodb
Cloudant Query using $or operator gives warning:
“no matching index found, create an index to optimize query time”
though indexing is present? The sample information is shown below:
Index USED:
db.index({
ddoc: "document_id",
type: "json",
index: {
fields: ["emailid", "mobileno"]
}
});
Query USED:
selector: {
$or: [
{
emailid: email_id
},
{
mobileno: mobile
}
]
}
You can find an issue in the couchdb project discussing something similar. "$or operator slow"
In the issue they conclude that the same field has to be present in both sides of the $or in order to select an index.
Your case doesn't meet this condition so the query will fall back into the _all_docs index (full scan of the db contents)
I have a collection like below
{
_id: ObjectId(),
account_number: someID,
account_context: {acnt_id:"1234",acnt_name:"Akhil",address:"Kadapa"},
tags:["tag","TaG","User","tag2","usr"]
},
{
_id: OBjectId(),
account_number: someID,
account_context: {acnt_id:"1234",acnt_name:"Akhil",address:"Kadapa"},
tags:["gat","GaT","Hello","tag2","Usr"]
}
I would like to query based on tags.
If I search for "tag" and "gat" , I should get both the documents
If I search for "Tag" , I should get first document
If I search for "tag" and "Hello", I should get both the documents.
Which means if the search field match for any one of the array element in the document I should get that document.
How can I get that?
you can use $elemMatch with $in for this problem like it:
var searchedArray = ["tag","Hello"]
collection.find({
tags: {$elemMatch: {$in:searchedArray}}
}, (err, result)=>{
})
$elemMatch check all elements of an array with her expression. my expression is $in that check filed with all values is there in searchedArray if equal accept it.