ravendb / ravendb-nodejs-client

RavenDB node.js client
MIT License
63 stars 31 forks source link

Query with search and then were uses OR instead of AND #410

Open ayende opened 5 months ago

ayende commented 5 months ago

The following code:

async function query(queryString: QueryString): Promise<Question[]> {
  const store = asyncLocalStorage.getStore() as alStoreType;
  const loggedinUserId = store?.loggedinUserId;
  const { language, level, searchTerm, isMarkedToBeRevised, limit, page, isRevised } = queryString;
  const isMarkedToBeRevisedBoolean = convertQueryParamsToBoolean(isMarkedToBeRevised);
  const isRevisedBoolean = convertQueryParamsToBoolean(isRevised);
  const session = ravenStore.openSession();
  const query = session.query<Question>({ collection: COLLECTION_NAME });

  if (limit) query.take(Number(limit));
  if (searchTerm) query.search("question", searchTerm);
  const skip = Number(page) * Number(limit);
  if (skip) query.skip(skip);

  if (!loggedinUserId) query.randomOrdering();
  else {
    const userCorrectAnswersIds = await session
      .query<UserCorrectAnswer>({
        collection: "UserCorrectAnswers",
      })
      .selectFields(["questionId"])
      .whereEquals("userId", loggedinUserId)
      .all();

    const docIdsToFilter = userCorrectAnswersIds.map(id =>
      setIdToCollectionName(COLLECTION_NAME, id as unknown as string)
    );
    query.not().whereIn("id()", docIdsToFilter);
  }

  const questions = await query.all();
  for (const question of questions) question.id = trimCollectionNameFromId(question.id);
  return questions;
}

Will generate a query with search("question", $p0) or not where("id()", ...)

Should be and not...

ml054 commented 3 months ago

This matches C#:

 using (var store = GetDocumentStore())
            {
                using (var s = store.OpenSession())
                {
                    var searchThenWhere = s.Advanced.DocumentQuery<User>()
                        .Search("Name", "Ayende")
                        .WhereEquals("Name", "fd")
                        .ToString();
                    var whereThenSearch = s.Advanced.DocumentQuery<User>()
                        .WhereEquals("Name", "fd")
                        .Search("Name", "Ayende")

                        .ToString();
                    var linq = s.Query<User>()
                        .Search(x => x.Name, "Ayende")
                        .Where(x => x.Name == "fd")
                        .ToString();
                }
            }

output:

linq: from 'Users' where search(Name, $p0) and (Name = $p1)
searchThenWhere: from 'Users' where search(Name, $p0) or Name = $p1
whereThenSearch: from 'Users' where Name = $p0 and search(Name, $p1)

Relevant line: https://github.com/ravendb/ravendb/blob/bcd841f2f9f0551b6359fc9cfa99e06400bfc07e/src/Raven.Client/Documents/Session/AbstractDocumentQuery.cs#L1651 Commit: https://github.com/ravendb/ravendb/commit/15e808d95eaca7db20be18d6c115dc268b6226b6