I'm trying order some data, and want to have the exact match as first results and then the rest.
I tried with this $eq in $project, but it seems that something won't work.
Is it possible to do something similar?
db.getCollection('words').aggregate([
{ $match: { "kanji.text": /^彼/ } },
{ $project: {
"kanji": 1,
"kana": 1,
"sense":1,
"exact": {
$eq : [ "$kanji.0.text", "彼" ]
}
}
},
{ $sort: {"exact": 1} }
])
Document Structure:
EDIT: I have found a bad workaround
db.getCollection('words').aggregate([
{ $match: { "kanji.text": /^彼/ } },
{ $limit : 10 },
{ $addFields: {
exact: {
$filter: {
input: '$kanji.text',
cond: {
$eq: ['$$this', "彼"]
}
}
}
}},
{ $project: {
"kanji": 1,
"kana": 1,
"sense":1,
"exact": 1
}
},
{ $sort: {"exact.0": -1} }
])
Related
I am learning Django with MongoDb and have a collection to search into. Here is a sample document in the collection:
{
"_id": { "$oid": "62615907568ddfca4fef3a25" },
"word": 'entropy,
"count": 4,
"occurrence": [
{"book": "62615907568ddfca4fef3a23", "year": 1942, "sentence": 0 },
{"book": "62615907568ddfca4fef3a23", "year": 1942, "sentence": 5 },
{"book": "62615907568ddfca4fef3a75", "year": 1928, "sentence": 0 },
{"book": "62615907568ddfca4fef3a90", "year": 1959, "sentence": 8 }
]
}
I want to retrieve the array elements of 'occurrence' field of a specific document (word):
Sorted by year
Within an year range
Limited with offset
count the total results (without limit/offset)
What I have done so far is:
offset= 0
limit= 10
search= {'$and': [{"_id": word_id_obj, "occurrence": {"$elemMatch": {"year": {"$gte": 1940, "$lte": 1960}}}}]}
word_docs= wordcollec.aggregate([
{"$match": search},
{"$project":
{"occurrence":
{"$slice": ['$occurrence', offset, limit]}
}
},
{"$sort": {'occurrence.year': -1}}
])
# Count total results
recnt= wordcollec.aggregate([{"$match": search}, {'$group' : {"_id": "$_id", "sno" : {"$sum" : {"$size": "$occurrence"}}}}])
The year range, count are not working and I am unable to sort them. How can I rewrite my query for this?
Thanks in advance.
Use $unwind then $sort
db.collection.aggregate([
{
$match: {
_id: { "$oid": "62615907568ddfca4fef3a25" },
occurrence: { $elemMatch: { year: { $gte: 1940, $lte: 1960 } } }
}
},
{
$set: { totalWithoutLimitOrOffset: { $size: "$occurrence" } }
},
{
$unwind: "$occurrence"
},
{
$match: { "occurrence.year": { $gte: 1940, $lte: 1960 } }
},
{
$sort: { "occurrence.year": -1 }
},
{
$skip: 1
},
{
$limit: 2
},
{
$group: {
_id: "$_id",
word: { $first: "$word" },
count: { $first: "$count" },
totalWithoutLimitOrOffset: { $first: "$totalWithoutLimitOrOffset" },
occurrence: { $push: "$occurrence" }
}
}
])
mongoplayground
I have a document like this:
{
"_id": "5ffc130e9fb31b26162e0bad",
"results": [
{
"customer": {
"display_name": "Manno Dispensary - first",
"ext_acct_id": "267"
}
},
{
"customer": {
"display_name": "Manno Dispensary - second",
"ext_acct_id": "262"
}
},
{
"customer": {
"display_name": "Kako Dispensary - first",
"ext_acct_id": "261"
}
},
{
"customer": {
"display_name": "Kako Dispensary - second",
"ext_acct_id": "263"
}
}
]
}
I want to write a MongoDB query which does a regex search on "customer.display_name" and returns all those documents in results that satisfies this criteria.
I have written this query till now, and it returns me the desired output, but the problem is, it is only retuning one document inside results, Am I missing anything in this?
my desired output:
{
"_id": "5ffc130e9fb31b26162e0bad",
"results": [
{
"customer": {
"display_name": "Manno Dispensary - first",
"ext_acct_id": "267"
}
},
{
"customer": {
"display_name": "Manno Dispensary - second",
"ext_acct_id": "262"
}
}
]
}
What I am actually getting:
{
"_id": "5ffc130e9fb31b26162e0bad",
"results": [
{
"customer": {
"display_name": "Manno Dispensary - first",
"ext_acct_id": "267"
}
}
]
}
this is the query which I have written to fetch all customers which contain "Manno" in their customer name.
My collection name is Order(mongoose), search="Manno"
Order.find({
results: {
$elemMatch : {
"customer.display_name": {$regex: search}
}
}
},{
results: {
$elemMatch : {
"customer.display_name": {$regex: search}
}
}
});
The $elemMatch and $ will return only single matching document/object form array, try $filter and $regexMatch,
$filter to iterate loop of results array
$regexMatch to check regular expression condition, it will return true or false
Order.find({
results: {
$elemMatch: {
"customer.display_name": { $regex: "Manno" }
}
}
},
{
results: {
$filter: {
input: "$results",
cond: {
$regexMatch: {
input: "$$this.customer.display_name",
regex: "Manno"
}
}
}
}
})
Playground
i am trying to filter with multiple value in loopback 3. 'AND condition' is not working. Numeric value filter working good but string value not matched.
this is my condition is now :
{ "and": [{ "id": { "neq": "5d146f1f7a62651b8162fcf3" } },
{ "gender": "male" }, { "age": { "between": [16, 60] } },
{ "interestId": { "inq": ["5d11c0ce59e2b64e8dc12956", "5d11c0e259e2b64e8dc12958", "5d11c08659e2b64e8dc12953", "5d11c01759e2b64e8dc1294b", "5d11c03759e2b64e8dc1294d"] } },
{ "location": { "near": { "lat": 26.8574194, "lng": 75.7977288 }, "maxDistance": 6, "unit": "kilometers" } },
{ "maritalStatus": { "like": {} } }, { "college": { "like": {} } },
{ "career": { "like": {} } }, { "currentJob": { "like": {} } },
{ "height": { "between": [50, 89] } }, { "weight": { "between": [72, 192] } }, { "bodyBuild": "Slim" }] }
String value is not push in array.
if (interestId.highSchool && interestId.highSchool !="") {
var highschool = new RegExp('.*' + interestId.highSchool + '.*', "i");
query.and.push({
highSchool: { like: highschool }
})
}
where is issue i don't understand. if i did't pass string value it's working fine.
Try following way:-
if (interestId.highSchool && interestId.highSchool !="") {
query.and.push({
highSchool: {regexp: new RegExp('.*' + interestId.highSchool + '.*', "i")}
})
}
I have this index:
{
"mappings": {
"records" : {
"properties" : {
"suggest" : {
"type" : "completion",
"contexts": [
{
"name": "year",
"type": "category",
"path": "year"
}
]
}
}
}
}
}
I put some records:
POST http://localhost:9200/example/records
{
"suggest": {
"input": "foo123" ,
"contexts": {
"year": "1999"
}
}
}
POST http://localhost:9200/example/records
{
"suggest": {
"input": "some123" ,
"contexts": {
"year": "1999"
}
}
}
POST http://localhost:9200/example/records
{
"suggest": {
"input": "thing123" ,
"contexts": {
"year": "2000"
}
}
}
Now I would do this query (sql like):
SELECT * FROM example WHERE SUGGEST LIKE %123% AND YEAR=1999
How can I do in Elastic Search?
I type:
POST http://localhost:9200/example/records/_search?pretty
{
"query": {
"bool": {
"must": [
{ "wildcard" : { "suggest" : "*123*" } }
],
"filter":[
{ "term" : { "year" : "1999" } }
]
}
}
}
I have returned this response with blank results:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
I am expecting to have returned this records:
foo123, year 1999
some123, year 1999
How can I do?
You need to use bool query with must if you care about score:
{
"query": {
"bool": {
"must": [
{ "wildcard" : { "name" : "*foo*" } },
{ "term" : { "year" : "1999" } }
]
}
}
}
or with filter if you just want to filter values and possibly cache the filter:
{
"query": {
"filter": {
"must": [
{ "wildcard" : { "name" : "*foo*" } },
{ "term" : { "year" : "1999" } }
]
}
}
}
I need to use $cond to combine differenet column, and one $cond I need to write is as following:
create_widget: {
$sum:{
$cond:[{$and: [ {$eq: ['$Method', 'POST']},
{Url:{$regex: /.*\/widgets$/}} ]}, 1, 0]
}
}
and this code is not right, it seems, regular expression can not be put here.Is there any other way to do this? I want to match Url and regular expression and put the code under $cond.
A sample data looks as
{"BrandId":"a","SessionId":"a1","Method":"POST","Url":"/sample/widgets"}
{"BrandId":"a","SessionId":"a2","Method":"POST","Url":"/sample/blog"}
{"BrandId":"b","SessionId":"b1","Method":"PUT","Url":"/sample/widgets"}
The whole code I wrote is as following:
db.tmpAll.aggregate([
{$group: {
_id: {BrandId:'$BrandId'},
SessionId: {$addToSet: '$SessionId'},
create_widget: {
$sum:{
$cond:[{$and: [ {$eq: ['$Method', 'POST']},
{} ]}, 1, 0]
}
}
}},
{$group: {
_id: '$_id.BrandId',
distinct_session: {$sum: {$size: '$SessionId'}},
create_widget: {$sum: '$create_widget'}
}}
]);
The expected result of sample code is
{ "_id" : "a", "distinct_session" : 2, "create_widget" : 1 }
{ "_id" : "b", "distinct_session" : 1, "create_widget" : 0 }
For MongoDB 4.2 and newer production releases, and in the 4.1.11 and newer development versions, use $regexMatch which is a syntactic sugar on top of $regexFind which can be used for regex matching and capturing.
db.tmpAll.aggregate([
{ "$group": {
"_id": {
"BrandId": "$BrandId",
"SessionId": "$SessionId"
},
"widget_count": {
"$sum": {
"$cond": [
{
"$and": [
{ "$eq": ["$Method", "POST"] },
{ "$regexMatch": {
"input": "$Url",
"regex": /widget/
} }
]
}, 1, 0
]
}
},
"session_count": { "$sum": 1 }
} },
{ "$group": {
"_id": "$_id.BrandId",
"create_widget": { "$sum": "$widget_count" },
"distinct_session": { "$sum": "$session_count" }
} }
]);
There is an open JIRA issue for this SERVER-8892 - Use $regex as the expression in a $cond. However, as a workaround, For older MongoDB versions which do not have the above features, use the following workaround in your aggregation pipeline.
It uses the $substr operator in the $project operator stage to extract the part of the URL and acts as a workaround for the regex. :
db.tmpAll.aggregate([
{ "$group": {
"_id": {
"BrandId": "$BrandId",
"SessionId": "$SessionId"
},
"widget_count": {
"$sum": {
"$cond": [
{
"$and": [
{ "$eq": ["$Method", "POST"] },
{ "$eq": [ { "$substr": [ "$Url", 8, -1 ] }, "widget"] }
]
}, 1, 0
]
}
},
"session_count": { "$sum": 1 }
} },
{ "$group": {
"_id": "$_id.BrandId",
"create_widget": { "$sum": "$widget_count" },
"distinct_session": { "$sum": "$session_count" }
} }
]);
Output
/* 1 */
{
"result" : [
{
"_id" : "a",
"create_widget" : 1,
"distinct_session" : 2
},
{
"_id" : "b",
"create_widget" : 0,
"distinct_session" : 1
}
],
"ok" : 1
}