Cloudant Query using $or operator gives warning - "no matching index found, create an index to optimize query time" though indexing is present? - couchdb

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)

Related

Usage of TSVECTOR and to_tsquery to filter records in Sequelize

I've been trying to get full search text to work for a while now without any success. The current documentation has this example:
[Op.match]: Sequelize.fn('to_tsquery', 'fat & rat') // match text search for strings 'fat' and 'rat' (PG only)
So I've built the following query:
Title.findAll({
where: {
keywords: {
[Op.match]: Sequelize.fn('to_tsquery', 'test')
}
}
})
And keywords is defined as a TSVECTOR field.
keywords: {
type: DataTypes.TSVECTOR,
},
It seems like it's generating the query properly, but I'm not getting the expected results. This is the query that it's being generated by Sequelize:
Executing (default): SELECT "id" FROM "Tests" AS "Test" WHERE "Test"."keywords" ## to_tsquery('test');
And I know that there are multiple records in the database that have 'test' in their vector, such as the following one:
{
"id": 3,
"keywords": "'keyword' 'this' 'test' 'is' 'a'",
}
so I'm unsure as to what's going on. What would be the proper way to search for matches based on a TSVECTOR field?
It's funny, but these days I am also working on the same thing and getting the same problem.
I think part of the solution is here (How to implement PostgresQL tsvector for full-text search using Sequelize?), but I haven't been able to get it to work yet.
If you find examples, I'm interested. Otherwise as soon as I find the solution that works 100% I will update this answer.
What I also notice is when I add data (seeds) from sequelize, it doesn't add the lexemes number after the data of the field in question. Do you have the same behavior ?
last thing, did you create the index ?
CREATE INDEX tsv_idx ON data USING gin(column);

Differences between $or and $in when querying Strings in MongoDB / mongoose

While building an API, I need to match documents that contain pending or active values for the key status.
When trying
args.status = {
$or: [
'active',
'pending'
]
}
I get an error: cannot use $or with string
However,
args.status = {
$in: [
'active',
'pending'
]
}
works just fine.
I would expect $or to work here. Can someone provide context on the differences between the two and why Strings require $in?
$or performs the logical OR operation on an ARRAY with more than two expressions e.g. {$or:[{name:"a"},{name:"b"}]} This query will return the record which are having either name 'a' or 'b'.
$in works on the array and return the documents which are which contains any of the field from your specified array e.g.{name:{$in:['a','b']}} This query will return the documents where name is either 'a' or 'b'.
Ideally both are doing same but just having the syntax difference.
In your case you have to modify your OR query syntax and add the condition expessions in an ARRAY.
{ $or: [
{
"args.status": "active"
},
{
"args.status": "pending"
}
]
}
Thats because $or expects array of objects. Objects that defines some filters out of which at least one needs to be match to return the result. For your particular scenario $in is the best option. Still if you wanna go with $or, the query will be like:
{
$or: [
{'args.status' : {$eq: 'active'}},
{'args.status' : {$eq: 'pending'}}
]
}
I'd suggest you stick with $in as it is the best fit for your requirement.
You can check the official docs for more details on $or
Hope this helps :)

Can we use $in and $nin together in a Mongoose query? [duplicate]

I have a MongoDB collection with records having a "name" field, I am trying to perform a find query where the name field appears twice in the query. I want to exclude certain names, via $nin, and perform regex search for other names. It doesn't seem to be working, as it returns all records. If I just have the regex search or the $nin search, it works as expected.
db.users.find({name:{$nin:[current_user]}).cb(array) - works
db.users.find({name:new RegExp(/query/)}).cb(array) - works
db.users.find({name:{$nin:[current_user]}, name:new RegExp(/query/)}).cb(array) - does NOT work, the current_user is NOT excluded from the find result.
I have a feeling, the find command takes the last query for multiple occurrences of the same field, is that so? And how do I get around it?
Thanks for help,
Gary
Your query JSON object contains name field two times, and it breaks the query. Pay attention to the $and mongo query operator. There are two ways to construct correct query:
1) db.users.find({ $and: [{ name: { $nin: [current_user] } }, { name: { $regex: new RegExp(/query/) } }] })
2) db.users.find({ name: { $nin: [current_user], $regex: new RegExp(/query/) } })
Also, if you exclude only one user, you can use $ne operator instead of $nin.

Getting element in array that matched text index query

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

How to use same field multiple times in MongoDB find query in NodeJS

I have a MongoDB collection with records having a "name" field, I am trying to perform a find query where the name field appears twice in the query. I want to exclude certain names, via $nin, and perform regex search for other names. It doesn't seem to be working, as it returns all records. If I just have the regex search or the $nin search, it works as expected.
db.users.find({name:{$nin:[current_user]}).cb(array) - works
db.users.find({name:new RegExp(/query/)}).cb(array) - works
db.users.find({name:{$nin:[current_user]}, name:new RegExp(/query/)}).cb(array) - does NOT work, the current_user is NOT excluded from the find result.
I have a feeling, the find command takes the last query for multiple occurrences of the same field, is that so? And how do I get around it?
Thanks for help,
Gary
Your query JSON object contains name field two times, and it breaks the query. Pay attention to the $and mongo query operator. There are two ways to construct correct query:
1) db.users.find({ $and: [{ name: { $nin: [current_user] } }, { name: { $regex: new RegExp(/query/) } }] })
2) db.users.find({ name: { $nin: [current_user], $regex: new RegExp(/query/) } })
Also, if you exclude only one user, you can use $ne operator instead of $nin.

Resources