Typesense 'OR' query mode - typesense

Description
I have a case where I'd like to search for multiple query tokens in a single collection like:
let searchRequests = {
'searches': [
{
'collection': 'products',
'q': 'shoe hat dress perfume',
}
]
}
each token contains results if I query them individually and also if I query two tokens like so: 'q': 'shoe hat',.
Is there a way to allow for more than two query items?
Expected Behavior
I expect to have results returned based on my query tokens 'shoe hat dress perfume', or in other words an OR query mode:
{
"results": [
{
"facet_counts": [],
"found": 100,
"hits": [
...
}
]
}
Actual Behavior
The actual behavior is that nothing is found:
{
"results": [
{
"facet_counts": [],
"found": 0,
"hits": [
...
}
]
}
Metadata
Typesense Version: 0.22.0

Typesense doesn't support strict ORs and currently have no plan to do so.
To solve my problem I used filter_by instead like so:
let searchRequests = {
'searches': [
{
'collection': 'products',
'q': '*',
'filter_by': "category:["shoe", "hat", "dress", "perfume"]"
}
]
}
This would return all products of category shoe/hat/dress/parfume.
More details on usage of filter_by here: https://typesense.org/docs/0.19.0/api/documents.html#index-a-document

Related

SQL Server Replace in MongoDB

I want to do a replace in projection. Like a SQL Server REPLACE. I'm pretty sure we can handle that in code but looking for some shell commands.
Here is what I have
db.OrderHistoryHeader.aggregate([
{
$project:{
"_id":0,
"OrderNo":1 // I want to do Replace(OrderNo,'XYZ','ABC')
}
}
],
{
allowDiskUse:true
}).pretty();
There's no built-in operator for that currently but you can use $indexOfBytes combined with $substr and $concat.
db.OrderHistoryHeader.aggregate([
{
$addFields:
{
index: { $indexOfBytes: [ "$OrderNo", "XYZ" ] },
}
},
{
$project: {
OrderNo: {
$concat: [
{ $substr: [ "$OrderNo", 0, "$index" ] },
"ABC",
{ $substr: [ "$OrderNo", { $add: [3, "$index"] }, -1 ] }
]
}
}
},
{
$project: {
index: 0
}
}
])
Where 3 is the length of text being replaced.
You can use the replaceOne method
db.collection.replaceOne(filter, replacement, options)
From documentation:
Behavior
replaceOne() replaces the first matching document in the collection that matches the filter, using the replacement document.
upsert
If upsert: true and no documents match the filter, db.collection.replaceOne() creates a new document based on the replacement document.

Query index in Cloudant doesn't return expected data

I have a Cloudant DB on Bluemix with an index defined as:
{
"index": {
"fields": [
{ "typ": "asc" },
{ "sen": "asc" },
{ "tim": "asc" }
]
},
"type": "json"
}
WHen I have a query of the form
{
"selector": {
"tim": {"$gt": millisecs},
"typ": "H"
},
"fields": ["sen","val","tim"],
"sort": [
{ "typ": "asc" },
{ "sen": "asc" },
{ "tim": "asc" }
],
"limit": readCount
}
it works perfectly. If I want to get everything, i.e. remove the condition typ="H", I get the error
"error":"no_usable_index","reason":"There is no index available for this selector."
I get the same response if I have "typ" : { "$in": ["H", "T"] }. I would have expected that the more generic query would work better than the one with extra selectors.
I just don't understand how this could be!
"typ" is the first field of your index, so is the basis of the ordering.
"tim", if it's the only element of the query, doesn't take advantage of the index, so it would trigger a full table scan if that query was allowed.
However you can ask explicitely for a full table scan if you add:
"_id": { "$gt": null }
See the doc, your case is not really described, but I think it's implied.
Did you try to create separate indexes for these fields and run the same query?

elasticsearch match two fields

How can I get this simple SQL query running on elasticsearch ?
SELECT * FROM [mytype] WHERE a = -23.4807339 AND b = -46.60068
I'm really having troubles with it's syntax, multi-match queries doesn't work in my case, which query type should I use?
For queries like yours bool filter is preferred over and filter. See here the whole story about this suggestion and why is considered to be more efficient.
These being said, I would choose to do it like this:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{"term": {"a": -23.4807339}},
{"term": {"b": -46.60068}}
]
}
}
}
}
}
You can approach this with the and filter. For your example, something like:
{
"size": 100,
"query" : {"filtered" : {
"query" : {"match_all" : {}},
"filter" : {"and" : [
"term" : {"a": -23.4807339},
"term" : {"b": -46.60068}
]}
}}
}
Be sure to direct the query against the correct index and type. Note that I specified the size of the return set as 100 arbitrarily - you'd have to specify a value that fits your use case.
There's more on filtered queries here, and more on the and filter here.

How to query mongodb with “like” for number data type? [duplicate]

I want to regex search an integer value in MongoDB. Is this possible?
I'm building a CRUD type interface that allows * for wildcards on the various fields. I'm trying to keep the UI consistent for a few fields that are integers.
Consider:
> db.seDemo.insert({ "example" : 1234 });
> db.seDemo.find({ "example" : 1234 });
{ "_id" : ObjectId("4bfc2bfea2004adae015220a"), "example" : 1234 }
> db.seDemo.find({ "example" : /^123.*/ });
>
As you can see, I insert an object and I'm able to find it by the value. If I try a simple regex, I can't actually find the object.
Thanks!
If you are wanting to do a pattern match on numbers, the way to do it in mongo is use the $where expression and pass in a pattern match.
> db.test.find({ $where: "/^123.*/.test(this.example)" })
{ "_id" : ObjectId("4bfc3187fec861325f34b132"), "example" : 1234 }
I am not a big fan of using the $where query operator because of the way it evaluates the query expression, it doesn't use indexes and the security risk if the query uses user input data.
Starting from MongoDB 4.2 you can use the $regexMatch|$regexFind|$regexFindAll available in MongoDB 4.1.9+ and the $expr to do this.
let regex = /123/;
$regexMatch and $regexFind
db.col.find({
"$expr": {
"$regexMatch": {
"input": {"$toString": "$name"},
"regex": /123/
}
}
})
$regexFinAll
db.col.find({
"$expr": {
"$gt": [
{
"$size": {
"$regexFindAll": {
"input": {"$toString": "$name"},
"regex": "123"
}
}
},
0
]
}
})
From MongoDB 4.0 you can use the $toString operator which is a wrapper around the $convert operator to stringify integers.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toString": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])
If what you want is retrieve all the document which contain a particular substring, starting from release 3.4, you can use the $redact operator which allows a $conditional logic processing.$indexOfCP.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toLower": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])
which produces:
{
"_id" : ObjectId("579c668c1c52188b56a235b7"),
"example" : 1234
}
{
"_id" : ObjectId("579c66971c52188b56a235b9"),
"example" : 12334
}
Prior to MongoDB 3.4, you need to $project your document and add another computed field which is the string value of your number.
The $toLower and his sibling $toUpper operators respectively convert a string to lowercase and uppercase but they have a little unknown feature which is that they can be used to convert an integer to string.
The $match operator returns all those documents that match your pattern using the $regex operator.
db.seDemo.aggregate(
[
{ "$project": {
"stringifyExample": { "$toLower": "$example" },
"example": 1
}},
{ "$match": { "stringifyExample": /^123.*/ } }
]
)
which yields:
{
"_id" : ObjectId("579c668c1c52188b56a235b7"),
"example" : 1234,
"stringifyExample" : "1234"
}
{
"_id" : ObjectId("579c66971c52188b56a235b9"),
"example" : 12334,
"stringifyExample" : "12334"
}
Now, if what you want is retrieve all the document which contain a particular substring, the easier and better way to do this is in the upcoming release of MongoDB (as of this writing) using the $redact operator which allows a $conditional logic processing.$indexOfCP.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toLower": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])

Elasticsearch/Tire text query DSL for excluding certain fields from being searched

I have a elastic search query like the following,
{
"query": {
"bool": {
"must": [
{
"query_string": {
"fields": ["title"],
"query": "test"
}
}
],
"must_not": [],
"should": []
}
},
"from": 0,
"size": 50,
"sort": [],
"facets": {}
}
I am able to execute an elastic search query on certain fields by giving a fields param to query_string as mentioned above. In my index mapping i have around 50 fields indexed. How do i query for all but one field. Something like an exclude option to query string. Is it possible with Tire/Elastic Search ?
I assumed it cannot be done and proceeded with getting all the mappings and parsing the hash which kinda sucks actually.