I want to write a query to make the search operations on partial words but not getting any kind of solution other than Atlas Search. I have one solution to use regex but by using regex query is taking more time even after I have created index on them.
I text search method, we can only provide the complete word which is not the scenario in our case.
For eg. - {$text:{$search:'Lionel Messi'}}, it will go for Lionel and messi in the fields but,
if {$text:{$search:'ione'}}, this is the query then it is not giving any result because the word is not a complete match.
I can not use only regex here as it is very time taking so do you have any suggestions or solutions?
Is there any way to make the searching on partial text?
Thanks in Advance.
I have tried searching about this but got no success, all I can get is the solution to go for Atlas search only.
For simple partial text search you may consider $indexOfCP , it is known to outperform $regex unless it is some case where complex $regex is necessary, example:
db.collection.aggregate([
{
$match: {
$expr: {
$gt: [
{
$indexOfCP: [
"$key",
"jump"
]
},
-1
]
}
}
}
])
or
db.collection.find(
{
$where: "this.key.indexOf('jump') >= 0"
}
).hint({key:1})
Playground1
Playground2
Related
Hi Logic Apps Experts,
I'd like to check with you some of the foreach loop behaviors, and to check whether this is expected/ is there any workarounds for this.
So the steps with this logicapps is to "Run query and list results" search will do is searching SecurityIncident table. And foreach SecurityIncident record, find a corresponding SecurityAlert record in "Using IncidentId-Query Details of the Alert" step.
For the first query, the data is parsed properly and each fields can be used.
However, after the second query I can only use 'Body' and 'value' in the steps. Which contains unparsed values.
Questions:
Is this behavior expected?
Is there a better way to ensure the second query is parsed?
Any other room of improvements advice are greatly appreciated.
Thank you!
The selection list affected by the required type/format of the input box in the action. So I think the behavior is expected.
If you want to get the parsed field from the query action, you can use expression. I'm not clear about the details of query result body, here I just provide a sample for your reference:
For example, if the query result shows like:
{
"body": [
{
"TenantId": "111",
"xxxx": "xxx"
},
{
"TenantId": "222",
"xxxx": "xxx"
}
]
}
Then you can use the expression body('Run_query_and_list_results')[0]?['TenantId'] to get the value of first TenantId. In a word, use [index] to get array, use ?['key'] to get map.
I have mongodb data model where I have some array fields that contain embedded objects or arrays. I have some inconsistencies in the field in question because I've tweaked my application logic. Initially, my model looked like this:
Initial Setup of Results collection
"competition" : "competition1",
"stats" : [
{
"stat1" : [],
"stat2" : []
}
]
However, I saw that this wasn't the best setup for my needs. So I changed it to the following:
New Setup of Results collection
"competition" : "competition1",
"stats" : [
{
"stat1" : 3,
"stat2" : 2
}
]
My problem now is that documents that have the initial setup cause an error. So what I want is to find all documents that have the initial setup and convert them to have the new setup.
How can I accomplish this in mongodb?
Here is what I've tried, but I'm stuck...
db.getCollection('results').find({"stats.0": { "$exists": true }})
But what I want is to be able to do something like
db.getCollection('results').find({"stats.0".stat1: { "$type": Array}})
Basically I want to get documents where the value of stats[0].stat1 is of type array and override the entire stats field to be an empty array.
This would fix the errors I'm getting.
$type operator for arrays in older versions works little differently than what you might think than $type in 3.6.
This will work in 3.6
db.getCollection('results').find( { "stats.0.stat1" : { $type: "array" } } )
You can do it couple of ways for lower versions and It depends what you are looking for.
For empty arrays you can just check
{"stats.0.stat1":{$size:0}}
For non empty arrays
{"stats.0.stat1": {$elemMatch:{ "$exists": true }}}
Combine both using $or for finding both empty and non empty array.
For your use case you can use below update
db.getCollection('results').update({"stats.0.stat1":{$size:0}}, {$set:{"stats":[]}})
I have a multivalued field which is filled by an array of strings. Now I want to find all documents that have i. e. foo as the i. e. second (!) string in this field. Is this possible?
If it is not, what would be your recommendation to achieve this?
For Solr, you can use UpdateRequestProcessor to copy and modify the field to add position prefix. So, you'll end up with 2_91 or similar. You can use StatelessScriptURP for that.
Alternatively, you could send this information as multiple fields and have dynamic field definition to map them.
Basically, for both Solr and ES, underlying Lucene stores multivalued strings as just one long string with large token offset between last token of first value and first token of second value. So, absolute positions require some sort of hack. Runtime hacks (e.g. ElasticSearch example in the other answer) are expensive during query. Content modifying hacks (e.g. URP in this example) are expensive with additional disk space or with more complex schema.
In elasticsearch, you can achieve this using Script Filter, Here is a sample,
consider a mapping for phone_no as,
{
"index": {
"mappings": {
"type": {
"properties": {
"phone_no": {
"type": "string"
}
}
}
}
}
}
put a document (first),
POST index/type
{
"phone_no" :["91","92210"]
}
and second one too,
POST index/type
{
"phone_no" :["92210","91"]
}
so, if you want to find the second value equals 91, then here is a query,
POST index/type/_search
{
"filter" :{
"script": {
"script": "_source.phone_no[1].equals(val)",
"params": {
"val" :"91"
}
}
}
}
where , val can be user defined,
Here in the above script, no case is handled (like, if it have size >1 , which may return execption sometime, you can modify script for your need ). Thanks,
Hope this might helps!!
Hello everyone and thanks in advance for any ideas, suggestions or answers.
First, the environment: I am using CouchDB (currently developing on 1.0.2) and couchdb-lucene 0.7. Obviously, I am using couchdb-lucene ("c-l" hereafter) to provide full-text searching within couchdb.
Second, let me provide everyone with an example couchdb document:
{
"_id": "5580c781345e4c65b0e75a220232acf5",
"_rev": "2-bf2921c3173163a18dc1797d9a0c8364",
"$type": "resource",
"$versionids": [
"5580c781345e4c65b0e75a220232acf5-0",
"5580c781345e4c65b0e75a220232acf5-1"
],
"$usagerights": [
{
"group-administrators": 31
},
{
"group-users": 3
}
],
"$currentversionid": "5580c781345e4c65b0e75a220232acf5-1",
"$tags": [
"Tag1",
"Tag2"
],
"$created": "/Date(1314973405895-0500)/",
"$creator": "administrator",
"$modified": "/Date(1314973405895-0500)/",
"$modifier": "administrator",
"$checkedoutat": "/Date(1314975155766-0500)/",
"$checkedoutto": "administrator",
"$lastcommit": "/Date(1314973405895-0500)/",
"$lastcommitter": "administrator",
"$title": "Test resource"
}
Third, let me explain what I want to do. I am trying to figure out how to index the '$usagerights' property. I am using the word index very loosely because I really do not care about being able to search it, I simply want to 'store' it so that it is returned with the search results. Anyway, the property is an array of json objects. Now, these json objects that compose the array will always have a single json property.
Based on my understanding of couchdb-lucene, I need to reduce this array to a comma separated string. I would expect something like "group-administrators:31,group-users:3" to be a final output.
Thus, my question is essentially: How can I reduce the $usagerights json array above to a comma separated string of key:value pairs within the couchdb design document as used by couchdb-lucene?
A previous question I posted regarding indexing of tagging in a similar situation, provided for reference: How-to index arrays (tags) in CouchDB using couchdb-lucene
Finally, if you need any additional details, please just post a comment and I will provide it.
Maybe I am missing something, but the only difference I see from your previous question, is that you should iterate on the objects. Then the code should be:
function(doc) {
var result = new Document(), usage, right;
for(var i in doc.$usagerights) {
usage = doc.$usagerights[i];
for(right in usage) {
result.add(right + ":" + usage[right]);
}
}
return result;
}
There's no requirement to convert to a comma-separated list of values (I'd be intrigued to know where you picked up that idea).
If you simply want the $usagerights item returned with your results, do this;
ret.add(JSON.stringify(doc.$usagerights),
{"index":"no", "store":"yes", "field":"usagerights"});
Lucene stores strings, not JSON, so you'll need to JSON.parse the string on query.
what seemed a simple task, came to be a challenge for me.
I have the following mongodb structure:
{
(...)
"services": {
"TCP80": {
"data": [{
"status": 1,
"delay": 3.87,
"ts": 1308056460
},{
"status": 1,
"delay": 2.83,
"ts": 1308058080
},{
"status": 1,
"delay": 5.77,
"ts": 1308060720
}]
}
}}
Now, the following query returns whole document:
{ 'services.TCP80.data.ts':{$gt:1308067020} }
I wonder - is it possible for me to receive only those "data" array entries matching $gt criteria (kind of shrinked doc)?
I was considering MapReduce, but could not locate even a single example on how to pass external arguments (timestamp) to Map() function. (This feature was added in 1.1.4 https://jira.mongodb.org/browse/SERVER-401)
Also, there's always an alternative to write storedJs function, but since we speak of large quantities of data, db-locks can't be tolerated here.
Most likely I'll have to redesign the structure to something 1-level deep, like:
{
status:1,delay:3.87,ts:138056460,service:TCP80
},{
status:1,delay:2.83,ts:1308058080,service:TCP80
},{
status:1,delay:5.77,ts:1308060720,service:TCP80
}
but DB will grow dramatically, since "service" is only one of many options which will append each document.
please advice!
thanks in advance
In version 2.1 with the aggregation framework you are now able to do this:
1: db.test.aggregate(
2: {$match : {}},
3: {$unwind: "$services.TCP80.data"},
4: {$match: {"services.TCP80.data.ts": {$gte: 1308060720}}}
5: );
You can use a custom criteria in line 2 to filter the parent documents. If you don't want to filter them, just leave line 2 out.
This is not currently supported. By default you will always receive the whole document/array unless you use field restrictions or the $slice operator. Currently these tools do not allow filtering the array elements based on the search criteria.
You should watch this request for a way to do this: https://jira.mongodb.org/browse/SERVER-828
I'm attempting to do something similar. I tried your suggestion of using the GROUP function, but I couldn't keep the embedded documents separate or was doing something incorrectly.
I needed to pull/get a subset of embedded documents by ID. Here's how I did it using Map/Reduce:
db.parent.mapReduce(
function(parent_id, child_ids){
if(this._id == parent_id)
emit(this._id, {children: this.children, ids: child_ids})
},
function(key, values){
var toReturn = [];
values[0].children.forEach(function(child){
if(values[0].ids.indexOf(product._id.toString()) != -1)
toReturn.push(child);
});
return {children: toReturn};
},
{
mapparams: [
"4d93b112c68c993eae000001", //example parent id
["4d97963ec68c99528d000007", "4debbfd5c68c991bba000014"] //example embedded children ids
]
}
).find()
I've abstracted my collection name to 'parent' and it's embedded documents to 'children'. I pass in two parameters: The parent document ID and an array of the embedded document IDs that I want to retrieve from the parent. Those parameters are passed in as the third parameter to the mapReduce function.
In the map function I find the parent document in the collection (which I'm pretty sure uses the _id index) and emit its id and children to the reduce function.
In the reduce function, I take the passed in document and loop through each of the children, collecting the ones with the desired ID. Looping through all the children is not ideal, but I don't know of another way to find by ID on an embedded document.
I also assume in the reduce function that there is only one document emitted since I'm searching by ID. If you expect more than one parent_id to match, than you will have to loop through the values array in the reduce function.
I hope this helps someone out there, as I googled everywhere with no results. Hopefully we'll see a built in feature soon from MongoDB, but until then I have to use this.
Fadi, as for "keeping embedded documents separate" - group should handle this with no issues
function getServiceData(collection, criteria) {
var res=db[collection].group({
cond: criteria,
initial: {vals:[],globalVar:0},
reduce: function(doc, out) {
if (out.globalVar%2==0)
out.vals.push({doc.whatever.kind.and.depth);
out.globalVar++;
},
finalize: function(out) {
if (vals.length==0)
out.vals='sorry, no data';
return out.vals;
}
});
return res[0];
};