问题
I have a collection (users) with the following structure:
{
propA: {
words: ["i", "have", "an","important", "question"]
}
}
I want to get autocomplete options from the db for some input in my website. So first, i think that i need to create an index for propA.words. Maybe something like this(?):
db.users.createIndex({ "propA.words" : 1 })
Second, how can i query this index to get all the words starting with X? For example, for the string "i", the query will retrieve ["i", "important"].
Thanks!
EDIT: This is the collection:
{
propA: {
words: ["aa","bb","cc","dd"]
}
}
{
propA: {
words: ["ab"]
}
}
{
propA: {
words: []
}
}
{
propB: []
}
Now, i want a query to get all the words that starts with "a". The query should return ["aa","ab"] on the above collection. I want the query to use only the index so the search will be efficient.
回答1:
You can use this aggregation, which iterates over the words array and matches the regex search string.
db.collection.aggregate( [
{
$addFields: {
matches: {
$filter: {
input: "$propA.words",
as: "w",
cond: {
$regexMatch: { input: "$$w" , regex: "^i" }
}
}
}
}
}
] )
The output:
{
"_id" : 1,
"propA" : {
"words" : [
"i",
"have",
"an",
"important",
"question"
]
},
"matches" : [
"i",
"important"
]
}
[ EDIT ADD ]
Now, i want a query to get all the words that starts with "a". The query should return ["aa","ab"] on the above collection. I want the query to use only the index so the search will be efficient.
The aggregation:
db.collection.aggregate( [
{
$match: { "propA.words": { $regex: "^a" } }
},
{
$unwind: "$propA.words"
},
{
$group: {
_id: null,
matchedWords: {
$addToSet: {
$cond: [ { $regexMatch: { input: "$propA.words", regex: "^a" } },
"$propA.words",
"$DUMMY" ]
}
}
}
},
{
$project: { _id: 0 }
}
] )
The result:
{ "matchedWords" : [ "ab", "aa" ] }
Index usage:
The index is created on the collection as follows:
db.collection.createIndex( { "propA.words": 1 } )
You can verify the index usage on the aggregation's $match stage by applying the explain and generating a query plan. For example:
db.collection.explain("executionStats").aggregate( [ ... ] )
回答2:
yes you make an index on the field, which is an array. then use regex query - the symbol ^ for 'starts with'... an index on an array field can create a big load... but your query being a 'start-with' is an efficient design....
来源:https://stackoverflow.com/questions/60727003/mongodb-autocomplete-get-all-words-starting-with-x