Javascript 使用AND运算符进行Mongoose文本搜索
所以我想做的是用mongoose对mongoDb进行“和”搜索,但结果是“或”搜索。有这样的设置吗?这是查询的外观:Javascript 使用AND运算符进行Mongoose文本搜索,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,所以我想做的是用mongoose对mongoDb进行“和”搜索,但结果是“或”搜索。有这样的设置吗?这是查询的外观: exampleModel.find({ $text: { $search: searchParams } }, { score: { $meta: "textScore" } }, { lean: true }).select(exampleViewModel).limit(1000).sort({ scor
exampleModel.find({
$text: {
$search: searchParams
}
}, {
score: {
$meta: "textScore"
}
}, { lean: true }).select(exampleViewModel).limit(1000).sort({
score: {
$meta: 'textScore'
}
}).exec(function (err, results) {
next(null, results);
});
让我们来看看searchParams=伦敦餐厅
这将在带有“餐厅”或“伦敦”字样的文档中产生结果我希望它能在带有“餐厅”和“伦敦”字样的文档中生成结果。在搜索词周围加上引号,将默认行为更改为AND
正如Carlos所提到的,一种可接受的解决方法是在单词搜索词周围加双引号,使其成为必填项:
apple banana => "apple" "banana"
这会产生类似于Elasticsearch等高级搜索引擎的和操作员的行为
但是,如果您打算通过前面的连字符(-exclude
)或确切的短语(“几个单词用双引号括起来”
)来支持单词排除,则在动态用户生成的查询上实现此功能可能会变得混乱,这两种语法都是$text
支持的有效语法
因此,我编写了一个函数,如果查询中的每个单词前面没有连字符,或者没有包含在一个确切的短语中,那么它会用双引号将每个单词包装起来
输入:
apple banana "huge orange trees" -pineapple "lemon"
"apple" "banana" "huge orange trees" -pineapple "lemon"
输出:
apple banana "huge orange trees" -pineapple "lemon"
"apple" "banana" "huge orange trees" -pineapple "lemon"
确保在每个双引号之前使用前面的反斜杠转义此函数的输出。然后,将其作为MongoDBfind()
查询的$search
参数传递
function wrapSingleTermsWithDoubleQuotes(query) {
// Output variable
var output = "";
// Keep track of whether to ignore the current word due to the negation operator (-minus)
var ignoreCurrentWord = false;
// Keep track of whether we're inside a custom phrase in the query ("exact match")
var withinCustomPhrase = false;
// Keep track of whether we need to close a double quote that we opened for the current word
var openedDoubleQuote = false;
// Remove all double spacing from the query (we may need a few iterations for this to work)
while (query.indexOf(' ') != -1) {
// Replace all occurrences of double spacing with single spacing
query = query.replace(/ /g, ' ');
}
// Trim leading and trailing spaces from the query to normalize the input
query = query.trim();
// Start traversing query characters
for (var i = 0; i < query.length; i++) {
// Comfort variable
var char = query[i];
// Not yet wrapping a term with double quotes?
if (!openedDoubleQuote) {
// Not ignoring the current word already (due to an operator) and not within a custom phrase?
if (!ignoreCurrentWord && !withinCustomPhrase) {
// Char is not a quote or negation operator?
if (char != '"' && char != '-') {
// This is most likely a single term, let's insert an opening double quote
output += '"';
// Mark this as true so we remember to close the double-quote when the word's done
openedDoubleQuote = true;
}
else {
// Char is a quote
if (char == '"') {
// Avoid adding quotes until we encounter the phrase's closing quote
withinCustomPhrase = !withinCustomPhrase;
}
// Char is a negation operator
else if (char == '-') {
// Ignore the current word (don't try to wrap it with double quotes)
ignoreCurrentWord = true;
}
}
}
else {
// Ignoring the current word or phrase -- check if we reached the end of the current word (space)
if (char == ' ') {
// In case this was a negative word, it's over now
ignoreCurrentWord = false;
// Were we inside a custom phrase, the current char is a space, and the previous char was a double quote?
if (withinCustomPhrase && i > 0 && query[i - 1] == '"') {
// No longer inside a the custom phrase (since we encountered a closing double-quote)
withinCustomPhrase = false;
}
}
}
}
else {
// Within a single term currently -- is current char a space, indicating the end of the single term?
if (char == ' ') {
// Add a closing double quote to finish wrapping the single term
output += '"';
// We closed our own double-quote
openedDoubleQuote = false;
}
}
// Add current char to output (we never omit any query chars, only append double-quotes where necessary)
output += char;
}
// Reached the end of the string but still got a quote to close?
if (openedDoubleQuote) {
// Add the final double quote
output += '"';
}
// Return algorithm output
return output;
}
函数wrapSingleTermsWithDoubleQuotes(查询){
//输出变量
var输出=”;
//跟踪是否由于否定运算符(-减号)而忽略当前单词
var ignoreCurrentWord=false;
//跟踪我们是否在查询中的自定义短语中(“精确匹配”)
var with incustomphrase=false;
//跟踪是否需要关闭为当前单词打开的双引号
var openedDoubleQuote=false;
//从查询中删除所有双倍间距(我们可能需要几次迭代才能工作)
while(query.indexOf(“”)!=-1){
//将所有出现的双间距替换为单间距
query=query.replace(//g',);
}
//修剪查询中的前导空格和尾随空格以规范化输入
query=query.trim();
//开始遍历查询字符
for(var i=0;i0&&query[i-1]==='''”){
//不再位于自定义短语的内部(因为我们遇到了结束双引号)
withinCustomPhrase=false;
}
}
}
}
否则{
//在当前单个术语内——当前字符是一个空格,表示单个术语的结束吗?
如果(字符=“”){
//添加结束双引号以完成对单个术语的包装
输出+=“”;
//我们结束了自己的双重报价
openedDoubleQuote=false;
}
}
//将当前字符添加到输出(我们从不忽略任何查询字符,只在必要时附加双引号)
输出+=字符;
}
//已到达字符串末尾,但仍有一个引号要关闭?
如果(openedDoubleQuote){
//添加最后的双引号
输出+=“”;
}
//返回算法输出
返回输出;
}
谢谢。我希望有一个选项,而不必操纵Searchparams字符串。